@zanfia/cli 0.9.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +16 -0
  2. package/dist/index.js +682 -150
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -33,9 +33,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
33
33
  mod
34
34
  ));
35
35
 
36
- // node_modules/commander/lib/error.js
36
+ // ../../../Zanfia2/apps/cli/node_modules/commander/lib/error.js
37
37
  var require_error = __commonJS({
38
- "node_modules/commander/lib/error.js"(exports) {
38
+ "../../../Zanfia2/apps/cli/node_modules/commander/lib/error.js"(exports) {
39
39
  "use strict";
40
40
  var CommanderError2 = class extends Error {
41
41
  /**
@@ -69,9 +69,9 @@ var require_error = __commonJS({
69
69
  }
70
70
  });
71
71
 
72
- // node_modules/commander/lib/argument.js
72
+ // ../../../Zanfia2/apps/cli/node_modules/commander/lib/argument.js
73
73
  var require_argument = __commonJS({
74
- "node_modules/commander/lib/argument.js"(exports) {
74
+ "../../../Zanfia2/apps/cli/node_modules/commander/lib/argument.js"(exports) {
75
75
  "use strict";
76
76
  var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
77
77
  var Argument2 = class {
@@ -197,9 +197,9 @@ var require_argument = __commonJS({
197
197
  }
198
198
  });
199
199
 
200
- // node_modules/commander/lib/help.js
200
+ // ../../../Zanfia2/apps/cli/node_modules/commander/lib/help.js
201
201
  var require_help = __commonJS({
202
- "node_modules/commander/lib/help.js"(exports) {
202
+ "../../../Zanfia2/apps/cli/node_modules/commander/lib/help.js"(exports) {
203
203
  "use strict";
204
204
  var { humanReadableArgName } = require_argument();
205
205
  var Help2 = class {
@@ -612,9 +612,9 @@ var require_help = __commonJS({
612
612
  }
613
613
  });
614
614
 
615
- // node_modules/commander/lib/option.js
615
+ // ../../../Zanfia2/apps/cli/node_modules/commander/lib/option.js
616
616
  var require_option = __commonJS({
617
- "node_modules/commander/lib/option.js"(exports) {
617
+ "../../../Zanfia2/apps/cli/node_modules/commander/lib/option.js"(exports) {
618
618
  "use strict";
619
619
  var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
620
620
  var Option2 = class {
@@ -885,9 +885,9 @@ var require_option = __commonJS({
885
885
  }
886
886
  });
887
887
 
888
- // node_modules/commander/lib/suggestSimilar.js
888
+ // ../../../Zanfia2/apps/cli/node_modules/commander/lib/suggestSimilar.js
889
889
  var require_suggestSimilar = __commonJS({
890
- "node_modules/commander/lib/suggestSimilar.js"(exports) {
890
+ "../../../Zanfia2/apps/cli/node_modules/commander/lib/suggestSimilar.js"(exports) {
891
891
  "use strict";
892
892
  var maxDistance = 3;
893
893
  function editDistance(a, b) {
@@ -966,9 +966,9 @@ var require_suggestSimilar = __commonJS({
966
966
  }
967
967
  });
968
968
 
969
- // node_modules/commander/lib/command.js
969
+ // ../../../Zanfia2/apps/cli/node_modules/commander/lib/command.js
970
970
  var require_command = __commonJS({
971
- "node_modules/commander/lib/command.js"(exports) {
971
+ "../../../Zanfia2/apps/cli/node_modules/commander/lib/command.js"(exports) {
972
972
  "use strict";
973
973
  var EventEmitter = __require("events").EventEmitter;
974
974
  var childProcess = __require("child_process");
@@ -3010,9 +3010,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3010
3010
  }
3011
3011
  });
3012
3012
 
3013
- // node_modules/commander/index.js
3013
+ // ../../../Zanfia2/apps/cli/node_modules/commander/index.js
3014
3014
  var require_commander = __commonJS({
3015
- "node_modules/commander/index.js"(exports) {
3015
+ "../../../Zanfia2/apps/cli/node_modules/commander/index.js"(exports) {
3016
3016
  "use strict";
3017
3017
  var { Argument: Argument2 } = require_argument();
3018
3018
  var { Command: Command4 } = require_command();
@@ -3033,9 +3033,9 @@ var require_commander = __commonJS({
3033
3033
  }
3034
3034
  });
3035
3035
 
3036
- // ../../node_modules/requires-port/index.js
3036
+ // ../../../Zanfia2/node_modules/requires-port/index.js
3037
3037
  var require_requires_port = __commonJS({
3038
- "../../node_modules/requires-port/index.js"(exports, module) {
3038
+ "../../../Zanfia2/node_modules/requires-port/index.js"(exports, module) {
3039
3039
  "use strict";
3040
3040
  module.exports = function required(port, protocol) {
3041
3041
  protocol = protocol.split(":")[0];
@@ -3060,9 +3060,9 @@ var require_requires_port = __commonJS({
3060
3060
  }
3061
3061
  });
3062
3062
 
3063
- // ../../node_modules/querystringify/index.js
3063
+ // ../../../Zanfia2/node_modules/querystringify/index.js
3064
3064
  var require_querystringify = __commonJS({
3065
- "../../node_modules/querystringify/index.js"(exports) {
3065
+ "../../../Zanfia2/node_modules/querystringify/index.js"(exports) {
3066
3066
  "use strict";
3067
3067
  var has = Object.prototype.hasOwnProperty;
3068
3068
  var undef;
@@ -3112,9 +3112,9 @@ var require_querystringify = __commonJS({
3112
3112
  }
3113
3113
  });
3114
3114
 
3115
- // ../../node_modules/url-parse/index.js
3115
+ // ../../../Zanfia2/node_modules/url-parse/index.js
3116
3116
  var require_url_parse = __commonJS({
3117
- "../../node_modules/url-parse/index.js"(exports, module) {
3117
+ "../../../Zanfia2/node_modules/url-parse/index.js"(exports, module) {
3118
3118
  "use strict";
3119
3119
  var required = require_requires_port();
3120
3120
  var qs = require_querystringify();
@@ -3420,9 +3420,9 @@ var require_url_parse = __commonJS({
3420
3420
  }
3421
3421
  });
3422
3422
 
3423
- // ../../node_modules/is-stream/index.js
3423
+ // ../../../Zanfia2/node_modules/is-stream/index.js
3424
3424
  var require_is_stream = __commonJS({
3425
- "../../node_modules/is-stream/index.js"(exports, module) {
3425
+ "../../../Zanfia2/node_modules/is-stream/index.js"(exports, module) {
3426
3426
  "use strict";
3427
3427
  var isStream2 = (stream) => stream !== null && typeof stream === "object" && typeof stream.pipe === "function";
3428
3428
  isStream2.writable = (stream) => isStream2(stream) && stream.writable !== false && typeof stream._write === "function" && typeof stream._writableState === "object";
@@ -3433,9 +3433,9 @@ var require_is_stream = __commonJS({
3433
3433
  }
3434
3434
  });
3435
3435
 
3436
- // ../../node_modules/lodash.throttle/index.js
3436
+ // ../../../Zanfia2/node_modules/lodash.throttle/index.js
3437
3437
  var require_lodash = __commonJS({
3438
- "../../node_modules/lodash.throttle/index.js"(exports, module) {
3438
+ "../../../Zanfia2/node_modules/lodash.throttle/index.js"(exports, module) {
3439
3439
  "use strict";
3440
3440
  var FUNC_ERROR_TEXT = "Expected a function";
3441
3441
  var NAN = 0 / 0;
@@ -3582,9 +3582,9 @@ var require_lodash = __commonJS({
3582
3582
  }
3583
3583
  });
3584
3584
 
3585
- // ../../node_modules/custom-error-instance/bin/factories.js
3585
+ // ../../../Zanfia2/node_modules/custom-error-instance/bin/factories.js
3586
3586
  var require_factories = __commonJS({
3587
- "../../node_modules/custom-error-instance/bin/factories.js"(exports) {
3587
+ "../../../Zanfia2/node_modules/custom-error-instance/bin/factories.js"(exports) {
3588
3588
  "use strict";
3589
3589
  exports.expectReceive = function(properties, configuration, factory) {
3590
3590
  var message;
@@ -3655,9 +3655,9 @@ var require_factories = __commonJS({
3655
3655
  }
3656
3656
  });
3657
3657
 
3658
- // ../../node_modules/custom-error-instance/bin/error.js
3658
+ // ../../../Zanfia2/node_modules/custom-error-instance/bin/error.js
3659
3659
  var require_error2 = __commonJS({
3660
- "../../node_modules/custom-error-instance/bin/error.js"(exports, module) {
3660
+ "../../../Zanfia2/node_modules/custom-error-instance/bin/error.js"(exports, module) {
3661
3661
  "use strict";
3662
3662
  module.exports = CustomError;
3663
3663
  CustomError.factory = require_factories();
@@ -3766,17 +3766,17 @@ var require_error2 = __commonJS({
3766
3766
  }
3767
3767
  });
3768
3768
 
3769
- // ../../node_modules/custom-error-instance/index.js
3769
+ // ../../../Zanfia2/node_modules/custom-error-instance/index.js
3770
3770
  var require_custom_error_instance = __commonJS({
3771
- "../../node_modules/custom-error-instance/index.js"(exports, module) {
3771
+ "../../../Zanfia2/node_modules/custom-error-instance/index.js"(exports, module) {
3772
3772
  "use strict";
3773
3773
  module.exports = require_error2();
3774
3774
  }
3775
3775
  });
3776
3776
 
3777
- // ../../node_modules/lodash._basetostring/index.js
3777
+ // ../../../Zanfia2/node_modules/lodash._basetostring/index.js
3778
3778
  var require_lodash2 = __commonJS({
3779
- "../../node_modules/lodash._basetostring/index.js"(exports, module) {
3779
+ "../../../Zanfia2/node_modules/lodash._basetostring/index.js"(exports, module) {
3780
3780
  "use strict";
3781
3781
  var INFINITY = 1 / 0;
3782
3782
  var symbolTag = "[object Symbol]";
@@ -3819,9 +3819,9 @@ var require_lodash2 = __commonJS({
3819
3819
  }
3820
3820
  });
3821
3821
 
3822
- // ../../node_modules/lodash._stringtopath/index.js
3822
+ // ../../../Zanfia2/node_modules/lodash._stringtopath/index.js
3823
3823
  var require_lodash3 = __commonJS({
3824
- "../../node_modules/lodash._stringtopath/index.js"(exports, module) {
3824
+ "../../../Zanfia2/node_modules/lodash._stringtopath/index.js"(exports, module) {
3825
3825
  "use strict";
3826
3826
  var baseToString = require_lodash2();
3827
3827
  var FUNC_ERROR_TEXT = "Expected a function";
@@ -4064,9 +4064,9 @@ var require_lodash3 = __commonJS({
4064
4064
  }
4065
4065
  });
4066
4066
 
4067
- // ../../node_modules/lodash._baseiteratee/index.js
4067
+ // ../../../Zanfia2/node_modules/lodash._baseiteratee/index.js
4068
4068
  var require_lodash4 = __commonJS({
4069
- "../../node_modules/lodash._baseiteratee/index.js"(exports, module) {
4069
+ "../../../Zanfia2/node_modules/lodash._baseiteratee/index.js"(exports, module) {
4070
4070
  "use strict";
4071
4071
  var stringToPath = require_lodash3();
4072
4072
  var LARGE_ARRAY_SIZE = 200;
@@ -4835,9 +4835,9 @@ var require_lodash4 = __commonJS({
4835
4835
  }
4836
4836
  });
4837
4837
 
4838
- // ../../node_modules/lodash._createset/index.js
4838
+ // ../../../Zanfia2/node_modules/lodash._createset/index.js
4839
4839
  var require_lodash5 = __commonJS({
4840
- "../../node_modules/lodash._createset/index.js"(exports, module) {
4840
+ "../../../Zanfia2/node_modules/lodash._createset/index.js"(exports, module) {
4841
4841
  "use strict";
4842
4842
  var INFINITY = 1 / 0;
4843
4843
  var funcTag = "[object Function]";
@@ -4924,9 +4924,9 @@ var require_lodash5 = __commonJS({
4924
4924
  }
4925
4925
  });
4926
4926
 
4927
- // ../../node_modules/lodash._root/index.js
4927
+ // ../../../Zanfia2/node_modules/lodash._root/index.js
4928
4928
  var require_lodash6 = __commonJS({
4929
- "../../node_modules/lodash._root/index.js"(exports, module) {
4929
+ "../../../Zanfia2/node_modules/lodash._root/index.js"(exports, module) {
4930
4930
  "use strict";
4931
4931
  var objectTypes = {
4932
4932
  "function": true,
@@ -4946,9 +4946,9 @@ var require_lodash6 = __commonJS({
4946
4946
  }
4947
4947
  });
4948
4948
 
4949
- // ../../node_modules/lodash._baseuniq/index.js
4949
+ // ../../../Zanfia2/node_modules/lodash._baseuniq/index.js
4950
4950
  var require_lodash7 = __commonJS({
4951
- "../../node_modules/lodash._baseuniq/index.js"(exports, module) {
4951
+ "../../../Zanfia2/node_modules/lodash._baseuniq/index.js"(exports, module) {
4952
4952
  "use strict";
4953
4953
  var createSet = require_lodash5();
4954
4954
  var root = require_lodash6();
@@ -5249,9 +5249,9 @@ var require_lodash7 = __commonJS({
5249
5249
  }
5250
5250
  });
5251
5251
 
5252
- // ../../node_modules/lodash.uniqby/index.js
5252
+ // ../../../Zanfia2/node_modules/combine-errors/node_modules/lodash.uniqby/index.js
5253
5253
  var require_lodash8 = __commonJS({
5254
- "../../node_modules/lodash.uniqby/index.js"(exports, module) {
5254
+ "../../../Zanfia2/node_modules/combine-errors/node_modules/lodash.uniqby/index.js"(exports, module) {
5255
5255
  "use strict";
5256
5256
  var baseIteratee = require_lodash4();
5257
5257
  var baseUniq = require_lodash7();
@@ -5262,9 +5262,9 @@ var require_lodash8 = __commonJS({
5262
5262
  }
5263
5263
  });
5264
5264
 
5265
- // ../../node_modules/combine-errors/index.js
5265
+ // ../../../Zanfia2/node_modules/combine-errors/index.js
5266
5266
  var require_combine_errors = __commonJS({
5267
- "../../node_modules/combine-errors/index.js"(exports, module) {
5267
+ "../../../Zanfia2/node_modules/combine-errors/index.js"(exports, module) {
5268
5268
  "use strict";
5269
5269
  var Custom = require_custom_error_instance();
5270
5270
  var uniq = require_lodash8();
@@ -5298,9 +5298,9 @@ var require_combine_errors = __commonJS({
5298
5298
  }
5299
5299
  });
5300
5300
 
5301
- // ../../node_modules/graceful-fs/polyfills.js
5301
+ // ../../../Zanfia2/node_modules/graceful-fs/polyfills.js
5302
5302
  var require_polyfills = __commonJS({
5303
- "../../node_modules/graceful-fs/polyfills.js"(exports, module) {
5303
+ "../../../Zanfia2/node_modules/graceful-fs/polyfills.js"(exports, module) {
5304
5304
  "use strict";
5305
5305
  var constants = __require("constants");
5306
5306
  var origCwd = process.cwd;
@@ -5587,9 +5587,9 @@ var require_polyfills = __commonJS({
5587
5587
  }
5588
5588
  });
5589
5589
 
5590
- // ../../node_modules/graceful-fs/legacy-streams.js
5590
+ // ../../../Zanfia2/node_modules/graceful-fs/legacy-streams.js
5591
5591
  var require_legacy_streams = __commonJS({
5592
- "../../node_modules/graceful-fs/legacy-streams.js"(exports, module) {
5592
+ "../../../Zanfia2/node_modules/graceful-fs/legacy-streams.js"(exports, module) {
5593
5593
  "use strict";
5594
5594
  var Stream = __require("stream").Stream;
5595
5595
  module.exports = legacy;
@@ -5684,9 +5684,9 @@ var require_legacy_streams = __commonJS({
5684
5684
  }
5685
5685
  });
5686
5686
 
5687
- // ../../node_modules/graceful-fs/clone.js
5687
+ // ../../../Zanfia2/node_modules/graceful-fs/clone.js
5688
5688
  var require_clone = __commonJS({
5689
- "../../node_modules/graceful-fs/clone.js"(exports, module) {
5689
+ "../../../Zanfia2/node_modules/graceful-fs/clone.js"(exports, module) {
5690
5690
  "use strict";
5691
5691
  module.exports = clone;
5692
5692
  var getPrototypeOf = Object.getPrototypeOf || function(obj) {
@@ -5707,9 +5707,9 @@ var require_clone = __commonJS({
5707
5707
  }
5708
5708
  });
5709
5709
 
5710
- // ../../node_modules/graceful-fs/graceful-fs.js
5710
+ // ../../../Zanfia2/node_modules/graceful-fs/graceful-fs.js
5711
5711
  var require_graceful_fs = __commonJS({
5712
- "../../node_modules/graceful-fs/graceful-fs.js"(exports, module) {
5712
+ "../../../Zanfia2/node_modules/graceful-fs/graceful-fs.js"(exports, module) {
5713
5713
  "use strict";
5714
5714
  var fs2 = __require("fs");
5715
5715
  var polyfills = require_polyfills();
@@ -6078,9 +6078,9 @@ var require_graceful_fs = __commonJS({
6078
6078
  }
6079
6079
  });
6080
6080
 
6081
- // ../../node_modules/proper-lockfile/node_modules/retry/lib/retry_operation.js
6081
+ // ../../../Zanfia2/node_modules/proper-lockfile/node_modules/retry/lib/retry_operation.js
6082
6082
  var require_retry_operation = __commonJS({
6083
- "../../node_modules/proper-lockfile/node_modules/retry/lib/retry_operation.js"(exports, module) {
6083
+ "../../../Zanfia2/node_modules/proper-lockfile/node_modules/retry/lib/retry_operation.js"(exports, module) {
6084
6084
  "use strict";
6085
6085
  function RetryOperation(timeouts, options) {
6086
6086
  if (typeof options === "boolean") {
@@ -6210,9 +6210,9 @@ var require_retry_operation = __commonJS({
6210
6210
  }
6211
6211
  });
6212
6212
 
6213
- // ../../node_modules/proper-lockfile/node_modules/retry/lib/retry.js
6213
+ // ../../../Zanfia2/node_modules/proper-lockfile/node_modules/retry/lib/retry.js
6214
6214
  var require_retry = __commonJS({
6215
- "../../node_modules/proper-lockfile/node_modules/retry/lib/retry.js"(exports) {
6215
+ "../../../Zanfia2/node_modules/proper-lockfile/node_modules/retry/lib/retry.js"(exports) {
6216
6216
  "use strict";
6217
6217
  var RetryOperation = require_retry_operation();
6218
6218
  exports.operation = function(options) {
@@ -6297,17 +6297,17 @@ var require_retry = __commonJS({
6297
6297
  }
6298
6298
  });
6299
6299
 
6300
- // ../../node_modules/proper-lockfile/node_modules/retry/index.js
6300
+ // ../../../Zanfia2/node_modules/proper-lockfile/node_modules/retry/index.js
6301
6301
  var require_retry2 = __commonJS({
6302
- "../../node_modules/proper-lockfile/node_modules/retry/index.js"(exports, module) {
6302
+ "../../../Zanfia2/node_modules/proper-lockfile/node_modules/retry/index.js"(exports, module) {
6303
6303
  "use strict";
6304
6304
  module.exports = require_retry();
6305
6305
  }
6306
6306
  });
6307
6307
 
6308
- // ../../node_modules/proper-lockfile/node_modules/signal-exit/signals.js
6308
+ // ../../../Zanfia2/node_modules/proper-lockfile/node_modules/signal-exit/signals.js
6309
6309
  var require_signals = __commonJS({
6310
- "../../node_modules/proper-lockfile/node_modules/signal-exit/signals.js"(exports, module) {
6310
+ "../../../Zanfia2/node_modules/proper-lockfile/node_modules/signal-exit/signals.js"(exports, module) {
6311
6311
  "use strict";
6312
6312
  module.exports = [
6313
6313
  "SIGABRT",
@@ -6343,9 +6343,9 @@ var require_signals = __commonJS({
6343
6343
  }
6344
6344
  });
6345
6345
 
6346
- // ../../node_modules/proper-lockfile/node_modules/signal-exit/index.js
6346
+ // ../../../Zanfia2/node_modules/proper-lockfile/node_modules/signal-exit/index.js
6347
6347
  var require_signal_exit = __commonJS({
6348
- "../../node_modules/proper-lockfile/node_modules/signal-exit/index.js"(exports, module) {
6348
+ "../../../Zanfia2/node_modules/proper-lockfile/node_modules/signal-exit/index.js"(exports, module) {
6349
6349
  "use strict";
6350
6350
  var process2 = global.process;
6351
6351
  var processOk = function(process3) {
@@ -6503,9 +6503,9 @@ var require_signal_exit = __commonJS({
6503
6503
  }
6504
6504
  });
6505
6505
 
6506
- // ../../node_modules/proper-lockfile/lib/mtime-precision.js
6506
+ // ../../../Zanfia2/node_modules/proper-lockfile/lib/mtime-precision.js
6507
6507
  var require_mtime_precision = __commonJS({
6508
- "../../node_modules/proper-lockfile/lib/mtime-precision.js"(exports, module) {
6508
+ "../../../Zanfia2/node_modules/proper-lockfile/lib/mtime-precision.js"(exports, module) {
6509
6509
  "use strict";
6510
6510
  var cacheSymbol = /* @__PURE__ */ Symbol();
6511
6511
  function probe(file, fs2, callback) {
@@ -6545,9 +6545,9 @@ var require_mtime_precision = __commonJS({
6545
6545
  }
6546
6546
  });
6547
6547
 
6548
- // ../../node_modules/proper-lockfile/lib/lockfile.js
6548
+ // ../../../Zanfia2/node_modules/proper-lockfile/lib/lockfile.js
6549
6549
  var require_lockfile = __commonJS({
6550
- "../../node_modules/proper-lockfile/lib/lockfile.js"(exports, module) {
6550
+ "../../../Zanfia2/node_modules/proper-lockfile/lib/lockfile.js"(exports, module) {
6551
6551
  "use strict";
6552
6552
  var path2 = __require("path");
6553
6553
  var fs2 = require_graceful_fs();
@@ -6782,9 +6782,9 @@ var require_lockfile = __commonJS({
6782
6782
  }
6783
6783
  });
6784
6784
 
6785
- // ../../node_modules/proper-lockfile/lib/adapter.js
6785
+ // ../../../Zanfia2/node_modules/proper-lockfile/lib/adapter.js
6786
6786
  var require_adapter = __commonJS({
6787
- "../../node_modules/proper-lockfile/lib/adapter.js"(exports, module) {
6787
+ "../../../Zanfia2/node_modules/proper-lockfile/lib/adapter.js"(exports, module) {
6788
6788
  "use strict";
6789
6789
  var fs2 = require_graceful_fs();
6790
6790
  function createSyncFs(fs3) {
@@ -6847,9 +6847,9 @@ var require_adapter = __commonJS({
6847
6847
  }
6848
6848
  });
6849
6849
 
6850
- // ../../node_modules/proper-lockfile/index.js
6850
+ // ../../../Zanfia2/node_modules/proper-lockfile/index.js
6851
6851
  var require_proper_lockfile = __commonJS({
6852
- "../../node_modules/proper-lockfile/index.js"(exports, module) {
6852
+ "../../../Zanfia2/node_modules/proper-lockfile/index.js"(exports, module) {
6853
6853
  "use strict";
6854
6854
  var lockfile2 = require_lockfile();
6855
6855
  var { toPromise, toSync, toSyncOptions } = require_adapter();
@@ -6883,7 +6883,7 @@ var require_proper_lockfile = __commonJS({
6883
6883
  }
6884
6884
  });
6885
6885
 
6886
- // node_modules/commander/esm.mjs
6886
+ // ../../../Zanfia2/apps/cli/node_modules/commander/esm.mjs
6887
6887
  var import_index = __toESM(require_commander(), 1);
6888
6888
  var {
6889
6889
  program,
@@ -7047,6 +7047,18 @@ function resolveApiKey(explicit) {
7047
7047
  const stored = readCredentials();
7048
7048
  return stored?.apiKey ?? null;
7049
7049
  }
7050
+ var MEMBER_WRITE_SCOPE = "communities:write";
7051
+ var FULL_MEMBER_SCOPES = ["communities:read", "communities:write"];
7052
+ function memberKeyScopes(claims) {
7053
+ return claims.scopes ?? [...FULL_MEMBER_SCOPES];
7054
+ }
7055
+ function isReadOnlyMemberKey(claims) {
7056
+ return !memberKeyScopes(claims).includes(MEMBER_WRITE_SCOPE);
7057
+ }
7058
+ function memberScopeLabel(claims) {
7059
+ const scopes = memberKeyScopes(claims).join(", ");
7060
+ return isReadOnlyMemberKey(claims) ? `${scopes} (read-only)` : scopes;
7061
+ }
7050
7062
  function decodeTokenClaims(token) {
7051
7063
  if (!token) return { kind: "workspace" };
7052
7064
  const parts = token.split(".");
@@ -7057,7 +7069,8 @@ function decodeTokenClaims(token) {
7057
7069
  kind: p.kind === "member" ? "member" : "workspace",
7058
7070
  workspaceId: typeof p.wsp === "string" ? p.wsp : void 0,
7059
7071
  subject: typeof p.sub === "string" ? p.sub : void 0,
7060
- expiresAt: typeof p.exp === "number" ? new Date(p.exp * 1e3).toISOString() : void 0
7072
+ expiresAt: typeof p.exp === "number" ? new Date(p.exp * 1e3).toISOString() : void 0,
7073
+ scopes: typeof p.scope === "string" ? p.scope.split(" ").filter(Boolean) : void 0
7061
7074
  };
7062
7075
  } catch {
7063
7076
  return { kind: "workspace" };
@@ -7380,7 +7393,8 @@ var mockBackend = {
7380
7393
  status: "draft",
7381
7394
  isFree: false,
7382
7395
  createdAt: now(),
7383
- clientCount: 0
7396
+ clientCount: 0,
7397
+ language: input.language ?? null
7384
7398
  };
7385
7399
  products.push(product);
7386
7400
  return toSummary(product);
@@ -7390,6 +7404,7 @@ var mockBackend = {
7390
7404
  if (!product) return null;
7391
7405
  if (input.name !== void 0) product.name = input.name;
7392
7406
  if (input.description !== void 0) product.description = input.description;
7407
+ if (input.language !== void 0) product.language = input.language;
7393
7408
  return { productId: id };
7394
7409
  },
7395
7410
  archiveProduct(id) {
@@ -7897,6 +7912,9 @@ function createMockClient() {
7897
7912
  async listClientTags() {
7898
7913
  return { count: 0, tags: [] };
7899
7914
  },
7915
+ async listClientCustomFields() {
7916
+ return { count: 0, fields: [] };
7917
+ },
7900
7918
  async createClientTag() {
7901
7919
  throw new ApiError(501, "client tag writes are not available in mock mode");
7902
7920
  },
@@ -8119,6 +8137,7 @@ function createMockClient() {
8119
8137
  przelewy24: false,
8120
8138
  paypal: false,
8121
8139
  dodo: false,
8140
+ tubapay: false,
8122
8141
  manual: null
8123
8142
  },
8124
8143
  sms: { defaultProvider: null, twilio: null, smsapi: null }
@@ -9248,6 +9267,7 @@ function createHttpClient(config) {
9248
9267
  ),
9249
9268
  changeClientEmail: (id, newEmail) => request("POST", `/clients/${encodeURIComponent(id)}/change-email`, { newEmail }),
9250
9269
  listClientTags: () => request("GET", "/clients/tags"),
9270
+ listClientCustomFields: (includeArchived) => request("GET", `/clients/custom-fields${includeArchived ? "?includeArchived=true" : ""}`),
9251
9271
  createClientTag: (input) => request("POST", "/clients/tags", input),
9252
9272
  updateClientTag: (tagId, input) => request("PATCH", `/clients/tags/${encodeURIComponent(tagId)}`, input),
9253
9273
  deleteClientTag: (tagId) => request("DELETE", `/clients/tags/${encodeURIComponent(tagId)}`),
@@ -10157,6 +10177,27 @@ function parseStorefrontVisibility(value) {
10157
10177
  }
10158
10178
  return visibility;
10159
10179
  }
10180
+ var PRODUCT_LANGUAGES = ["pl", "en"];
10181
+ var PRODUCT_LANGUAGE_NONE = "none";
10182
+ function parseProductLanguage(value) {
10183
+ const language = PRODUCT_LANGUAGES.find((candidate) => candidate === value.trim().toLowerCase());
10184
+ if (language === void 0) {
10185
+ throw new Error(
10186
+ `Invalid --language: ${value} (expected one of: ${PRODUCT_LANGUAGES.join(", ")})`
10187
+ );
10188
+ }
10189
+ return language;
10190
+ }
10191
+ function parseProductLanguageOrNone(value) {
10192
+ if (value.trim().toLowerCase() === PRODUCT_LANGUAGE_NONE) return PRODUCT_LANGUAGE_NONE;
10193
+ const language = PRODUCT_LANGUAGES.find((candidate) => candidate === value.trim().toLowerCase());
10194
+ if (language === void 0) {
10195
+ throw new Error(
10196
+ `Invalid --language: ${value} (expected one of: ${PRODUCT_LANGUAGES.join(", ")}, ${PRODUCT_LANGUAGE_NONE})`
10197
+ );
10198
+ }
10199
+ return language;
10200
+ }
10160
10201
  function parseCommaList(flag) {
10161
10202
  return (value) => {
10162
10203
  const items = [
@@ -10327,18 +10368,19 @@ function registerCertificatesCommands(program2) {
10327
10368
  "Course-completion and event-participation certificates \u2014 issue for course or event clients, revoke/reinstate, resend the email, and manage designer templates (`certificates templates \u2026`)"
10328
10369
  );
10329
10370
  certificates.command("list").summary("List certificates").description(
10330
- "Issued certificates of the workspace (course completion and event participation), newest first, optionally filtered to one product (`productId`); `limit` caps the rows (service default applies). Each row is the credential: public `certificateId` (`cert_\u2026`, the id every certificate write takes), `productType` (`course` / `event`), recipient name/email, product (`courseName`) and issuer names, completion/issued dates, `issuedBy` (manual vs automatic), template id/version, PDF and verification URLs, `status` (active/revoked), `expiresAt` and delivery/engagement signals (email status, views, downloads, LinkedIn add). Also the polling endpoint after issue-certificates \u2014 a newly enqueued client shows up here once its PDF has been rendered."
10371
+ "Issued certificates of the workspace (course completion and event participation), newest first, optionally filtered to one product (`productId`); `limit` caps the rows per page (service default applies) and `nextCursor` (pass it back as `cursor`) continues the list. Each row is the credential: public `certificateId` (`cert_\u2026`, the id every certificate write takes), `productType` (`course` / `event`), recipient name/email, product (`courseName`) and issuer names, completion/issued dates, `issuedBy` (manual vs automatic), template id/version, PDF and verification URLs, `status` (active/revoked), `expiresAt` and delivery/engagement signals (email status, views, downloads, LinkedIn add). Also the polling endpoint after issue-certificates \u2014 a newly enqueued client shows up here once its PDF has been rendered."
10331
10372
  ).option("--product <value>", "Course or event product id \u2014 omit for all products.").option(
10332
10373
  "--limit <n>",
10333
- "Max rows, newest first (max 500; the service default applies when omitted).",
10374
+ "Max rows per page, newest first (max 500; the service default applies when omitted).",
10334
10375
  parseNumberOption("--limit", NumberFormat.Integer)
10335
- ).action(async (options, command) => {
10376
+ ).option("--cursor <value>", "`nextCursor` of the previous page; omit for the first page.").action(async (options, command) => {
10336
10377
  const flags = getGlobalFlags(command);
10337
10378
  const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
10338
10379
  const params = {};
10339
10380
  const payload = {
10340
10381
  productId: options.product,
10341
- limit: options.limit
10382
+ limit: options.limit,
10383
+ cursor: options.cursor
10342
10384
  };
10343
10385
  const result = await client.call("GET", "/certificates", params, payload, void 0);
10344
10386
  const rows = tableRowsOf(result, "certificates");
@@ -10566,6 +10608,84 @@ function registerCertificatesCommands(program2) {
10566
10608
  );
10567
10609
  emit(flags, result ?? {}, () => printJson(result ?? {}));
10568
10610
  });
10611
+ const certificatesSettings = certificates.command("settings");
10612
+ certificatesSettings.description(
10613
+ "A course's or event's certificate settings (auto-issue, layout, numbering, date, claim)"
10614
+ );
10615
+ certificatesSettings.command("get").summary("A product's certificate settings").description(
10616
+ 'Certificate settings of one course or event product \u2014 the same fields as the dashboard\'s product Settings \u2192 Certificate section: `certificateEnabled` (automatic certificate on course completion; courses only, always false for an event), `certificateTemplateId` (null = the workspace default template), `certificateCustomText` (the extra line printed by templates with the "custom text" element), `certificateValidityMonths` (null = never expires), numbering (`certificateCode`), the printed date (`certificateDateMode` + `certificateTrainingDate`) and claim mode (`certificateClaimEnabled` + `certificateClaimAvailableFrom`). 404 for an unknown product, 400 for a product type without certificates.'
10617
+ ).argument("<productId>", "Course or event product id (other product types answer 400).").action(async (productId, _options, command) => {
10618
+ const flags = getGlobalFlags(command);
10619
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
10620
+ const params = {
10621
+ productId
10622
+ };
10623
+ const result = await client.call(
10624
+ "GET",
10625
+ "/products/:productId/certificate-settings",
10626
+ params,
10627
+ void 0,
10628
+ void 0
10629
+ );
10630
+ emit(flags, result ?? {}, () => printJson(result ?? {}));
10631
+ });
10632
+ certificatesSettings.command("update").summary("Update a product's certificate settings").description(
10633
+ "Partial update of one course or event product's certificate settings \u2014 what the dashboard's product Settings \u2192 Certificate section saves: automatic certificate on course completion (`certificateEnabled`, courses only), layout (`certificateTemplateId`), the extra line (`certificateCustomText`, max 300 characters / 3 lines), validity, numbering (`certificateCode`), the printed date (`certificateDateMode` + `certificateTrainingDate`) and claim mode (`certificateClaimEnabled` + `certificateClaimAvailableFrom`). Absent fields stay unchanged, null clears; an empty body is a 400. The whole patch is checked before anything is saved (409 taken code, 404 unknown product or template, 400 invalid value). Only certificates issued from now on use the new settings. Answers the settings as saved."
10634
+ ).argument("<productId>", "Course or event product id (other product types answer 400).").option(
10635
+ "--auto-issue",
10636
+ "Automatic certificate on course completion. Course products only (400 on an event)."
10637
+ ).option("--no-auto-issue", "Send `certificateEnabled: false` explicitly.").option(
10638
+ "--template <value>",
10639
+ "Certificate template id from list-certificate-templates (404 when not in this workspace); null or blank = back to the workspace default."
10640
+ ).option(
10641
+ "--custom-text <value>",
10642
+ 'Extra line printed by templates with the "custom text" element, e.g. training hours. Max 300 characters and 3 lines (line breaks kept); null or blank clears it.'
10643
+ ).option(
10644
+ "--validity-months <n>",
10645
+ "Validity in months from issuance; null = never expires.",
10646
+ parseNumberOption("--validity-months", NumberFormat.Integer)
10647
+ ).option(
10648
+ "--code <value>",
10649
+ "Exactly 3 digits (`017`), unique in the workspace (409 when another product has it); numbers certificates `{seq}/{code}/{schoolYear}`. null or blank = unnumbered."
10650
+ ).addOption(
10651
+ new Option(
10652
+ "--date-mode <completion|training_date|issue_date>",
10653
+ "Printed date: `completion` (course progress, else the issue date), `training_date` (needs certificateTrainingDate) or `issue_date`. null = completion."
10654
+ ).choices(["completion", "training_date", "issue_date"])
10655
+ ).option(
10656
+ "--training-date <value>",
10657
+ "`YYYY-MM-DD`, printed in the `training_date` mode; null or blank clears."
10658
+ ).option("--claim", "Participants claim the certificate themselves in the portal (claim mode).").option("--no-claim", "Send `certificateClaimEnabled: false` explicitly.").option(
10659
+ "--claim-from <value>",
10660
+ "First claim day `YYYY-MM-DD`; null or blank = the day after the training date (else at once)."
10661
+ ).action(
10662
+ async (productId, options, command) => {
10663
+ const flags = getGlobalFlags(command);
10664
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
10665
+ const params = {
10666
+ productId
10667
+ };
10668
+ const payload = {
10669
+ certificateEnabled: options.autoIssue,
10670
+ certificateTemplateId: options.template,
10671
+ certificateCustomText: options.customText,
10672
+ certificateValidityMonths: options.validityMonths,
10673
+ certificateCode: options.code,
10674
+ certificateDateMode: options.dateMode,
10675
+ certificateTrainingDate: options.trainingDate,
10676
+ certificateClaimEnabled: options.claim,
10677
+ certificateClaimAvailableFrom: options.claimFrom
10678
+ };
10679
+ const result = await client.call(
10680
+ "PATCH",
10681
+ "/products/:productId/certificate-settings",
10682
+ params,
10683
+ void 0,
10684
+ payload
10685
+ );
10686
+ emit(flags, result ?? {}, () => printJson(result ?? {}));
10687
+ }
10688
+ );
10569
10689
  }
10570
10690
 
10571
10691
  // src/commands/_generated/blog.ts
@@ -10699,10 +10819,270 @@ function registerBlogCommands(program2) {
10699
10819
  });
10700
10820
  }
10701
10821
 
10822
+ // src/commands/_generated/site-redirects.ts
10823
+ var listSiteRedirectsColumns = ["from", "to", "kind"];
10824
+ function registerSiteRedirectsCommands(program2) {
10825
+ const siteRedirects = program2.command("site-redirects");
10826
+ siteRedirects.description(
10827
+ "The site's 301 redirect map (Your site \u2192 Redirects): old addresses and where they go; checked by the same rules as the dashboard"
10828
+ );
10829
+ siteRedirects.command("list").summary("List site redirects").description(
10830
+ "The site's 301 redirect map (dashboard: Your site \u2192 Redirects): old addresses of a site moved to Zanfia and where they go now, in map order, plus `max` (the cap). A line fires only when nothing on the site answers the address. `kind` = `exact` (one address) or `folder` (`/news/*`, every address under it). The `from` of a line is its id for update-site-redirect and delete-site-redirect."
10831
+ ).action(async (_options, command) => {
10832
+ const flags = getGlobalFlags(command);
10833
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
10834
+ const params = {};
10835
+ const result = await client.call("GET", "/site/redirects", params, void 0, void 0);
10836
+ const rows = tableRowsOf(result, "redirects");
10837
+ emit(flags, result ?? {}, () => printTable(rows, listSiteRedirectsColumns));
10838
+ });
10839
+ siteRedirects.command("create").summary("Add a site redirect").description(
10840
+ "Adds one line at the end of the site's 301 map; live at once. Refused (400 `site-redirects-refused`, `issues[]` = index, from, to, issue) exactly like the dashboard save: a malformed address (`invalid-from` / `invalid-to`), the home page or an address Zanfia owns (`/blog`, `/p/\u2026`, `/app`: `reserved-from`), the member area (`portal-from`), a published page (`page-exists`), a `from` the map already has (`duplicate`), a chain or a loop (`chain`), `/*` in `to` without a folder `from` (`rest-without-folder`), over 500 lines (`too-many-entries`). Returns the line as stored."
10841
+ ).argument(
10842
+ "<from>",
10843
+ "The old address on the site: a path (`/o-nas`), a full address on the site (`https://example.com/o-nas/`, stored as its path) or a folder ending with `/*` (`/news/*`, every address under it). Query string and `#\u2026` are dropped; case is kept."
10844
+ ).argument(
10845
+ "<to>",
10846
+ "Where it goes: a path on the site (`/o-mnie`; a folder line may end with `/*` to keep the rest of the old address: `/news/*` \u2192 `/blog/*`) or an absolute `https://` address."
10847
+ ).action(async (from, to, _options, command) => {
10848
+ const flags = getGlobalFlags(command);
10849
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
10850
+ const params = {};
10851
+ const payload = {
10852
+ from,
10853
+ to
10854
+ };
10855
+ const result = await client.call("POST", "/site/redirects", params, void 0, payload);
10856
+ emit(flags, result ?? {}, () => printJson(result ?? {}));
10857
+ });
10858
+ siteRedirects.command("update").summary("Change a site redirect").description(
10859
+ "Changes one line of the 301 map, picked by its current `from`: `newFrom`, `to` or both; a field not given keeps its value and the line keeps its place. Live at once. 404 `site-redirect-not-found` when no line has that `from`; refused like create-site-redirect (400 `site-redirects-refused` with `issues[]`). Returns the line as stored."
10860
+ ).argument(
10861
+ "<from>",
10862
+ "The line to change, by its current `from` (as list-site-redirects shows it; `/o-nas/` or a full address on the site also match)."
10863
+ ).option(
10864
+ "--new-from <value>",
10865
+ "The old address on the site: a path (`/o-nas`), a full address on the site (`https://example.com/o-nas/`, stored as its path) or a folder ending with `/*` (`/news/*`, every address under it). Query string and `#\u2026` are dropped; case is kept."
10866
+ ).option(
10867
+ "--to <value>",
10868
+ "Where it goes: a path on the site (`/o-mnie`; a folder line may end with `/*` to keep the rest of the old address: `/news/*` \u2192 `/blog/*`) or an absolute `https://` address."
10869
+ ).action(async (from, options, command) => {
10870
+ const flags = getGlobalFlags(command);
10871
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
10872
+ const params = {};
10873
+ const payload = {
10874
+ from,
10875
+ newFrom: options.newFrom,
10876
+ to: options.to
10877
+ };
10878
+ const result = await client.call("PATCH", "/site/redirects", params, void 0, payload);
10879
+ emit(flags, result ?? {}, () => printJson(result ?? {}));
10880
+ });
10881
+ siteRedirects.command("delete").summary("Remove a site redirect").description(
10882
+ "Removes one line of the 301 map, picked by its `from` (sent in the JSON body). The old address answers 404 again at once (links to it in search results and old posts break). 404 `site-redirect-not-found` when no line has that `from`. Returns the removed line."
10883
+ ).argument(
10884
+ "<from>",
10885
+ "The line to change, by its current `from` (as list-site-redirects shows it; `/o-nas/` or a full address on the site also match)."
10886
+ ).option(
10887
+ "--confirm",
10888
+ "required \u2014 acknowledge that you want to the old address answers 404 again"
10889
+ ).action(async (from, options, command) => {
10890
+ const flags = getGlobalFlags(command);
10891
+ requireConfirm(options.confirm, "the old address answers 404 again");
10892
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
10893
+ const params = {};
10894
+ const payload = {
10895
+ from
10896
+ };
10897
+ const result = await client.call("DELETE", "/site/redirects", params, void 0, payload);
10898
+ emit(flags, result ?? {}, () => printJson(result ?? {}));
10899
+ });
10900
+ }
10901
+
10902
+ // src/commands/_generated/popups.ts
10903
+ var listPopupsColumns = ["id", "name", "status", "priority", "updatedAt"];
10904
+ function registerPopupsCommands(program2) {
10905
+ const popups = program2.command("popups");
10906
+ popups.description(
10907
+ "Pop-ups on the workspace site (Your site \u2192 Pop-ups): a signup form shown on entry or after scrolling, after the cookie decision, never again after a signup"
10908
+ );
10909
+ popups.command("list").summary("List pop-ups").description(
10910
+ "Every pop-up of the workspace site (drafts, active, paused) in priority order: copy, form content, triggers per device, targeting, frequency and schedule. The id source for every other pop-up tool."
10911
+ ).action(async (_options, command) => {
10912
+ const flags = getGlobalFlags(command);
10913
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
10914
+ const params = {};
10915
+ const result = await client.call("GET", "/popups", params, void 0, void 0);
10916
+ const rows = tableRowsOf(result, "popups");
10917
+ emit(flags, result ?? {}, () => printTable(rows, listPopupsColumns));
10918
+ });
10919
+ popups.command("create").summary("Create a pop-up").description(
10920
+ "Creates a pop-up as a DRAFT holding a signup form. Without `content.formId` a new standalone signup form named after the pop-up is created (visible in Forms). Defaults: desktop after 10 s on the page, phones after 40 % scroll as a bottom sheet, again after 7 days, all hosted pages except thank-you / download / member pages, hidden for subscribers. Activate it with set-popup-status once it has a title and a button text. Requires the pop-ups feature on the plan (403 otherwise)."
10921
+ ).requiredOption(
10922
+ "--name <value>",
10923
+ "Internal name (panel only); also the name of a provisioned form."
10924
+ ).option(
10925
+ "--priority <n>",
10926
+ "Lower shows first when several pop-ups match a page; default = after the others.",
10927
+ parseNumberOption("--priority", NumberFormat.Integer)
10928
+ ).addOption(
10929
+ new Option(
10930
+ "--language <pl|en|default>",
10931
+ "Built-in labels (close, errors): `pl`, `en` or `default` (= the page language)."
10932
+ ).choices(["pl", "en", "default"])
10933
+ ).option(
10934
+ "--copy <json|file>",
10935
+ "Headline, text, button and image.",
10936
+ parseJsonObjectFileOrInline("--copy")
10937
+ ).option(
10938
+ "--content <json|file>",
10939
+ "What the pop-up holds: a signup form.",
10940
+ parseJsonObjectFileOrInline("--content")
10941
+ ).option("--design <json|file>", "design", parseJsonObjectFileOrInline("--design")).option(
10942
+ "--trigger <json|file>",
10943
+ "When it opens, per device.",
10944
+ parseJsonObjectFileOrInline("--trigger")
10945
+ ).option(
10946
+ "--targeting <json|file>",
10947
+ "Where and for whom.",
10948
+ parseJsonObjectFileOrInline("--targeting")
10949
+ ).option(
10950
+ "--frequency <json|file>",
10951
+ "How often one visitor sees it; never again after a signup. Default every 7 days.",
10952
+ parseJsonObjectFileOrInline("--frequency")
10953
+ ).option(
10954
+ "--schedule <json|file>",
10955
+ "From / to (applied within a few minutes).",
10956
+ parseJsonObjectFileOrInline("--schedule")
10957
+ ).action(async (options, command) => {
10958
+ const flags = getGlobalFlags(command);
10959
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
10960
+ const params = {};
10961
+ const payload = {
10962
+ name: options.name,
10963
+ priority: options.priority,
10964
+ language: options.language,
10965
+ copy: options.copy,
10966
+ content: options.content,
10967
+ design: options.design,
10968
+ trigger: options.trigger,
10969
+ targeting: options.targeting,
10970
+ frequency: options.frequency,
10971
+ schedule: options.schedule
10972
+ };
10973
+ const result = await client.call("POST", "/popups", params, void 0, payload);
10974
+ emit(flags, result ?? {}, () => printJson(result ?? {}));
10975
+ });
10976
+ popups.command("get").summary("Pop-up detail").description(
10977
+ "One pop-up in full: status, copy, form content, triggers, targeting, frequency, schedule."
10978
+ ).argument("<id>", "Pop-up id (`popup_\u2026`) from list-popups.").action(async (id, _options, command) => {
10979
+ const flags = getGlobalFlags(command);
10980
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
10981
+ const params = {
10982
+ popupId: id
10983
+ };
10984
+ const result = await client.call("GET", "/popups/:popupId", params, void 0, void 0);
10985
+ emit(flags, result ?? {}, () => printJson(result ?? {}));
10986
+ });
10987
+ popups.command("update").summary("Update a pop-up").description(
10988
+ "Partial update of a pop-up: each section sent merges into the current one (copy, content, design, targeting, schedule field by field; a trigger rule, the page list and the frequency are replaced whole). An active pop-up must keep its title, button and form (400 popup-incomplete). Live sites pick changes up within a few minutes."
10989
+ ).argument("<id>", "Pop-up id (`popup_\u2026`) from list-popups.").option("--name <value>", "Internal name (panel only).").option(
10990
+ "--priority <n>",
10991
+ "Lower shows first when several pop-ups match a page; default = after the others.",
10992
+ parseNumberOption("--priority", NumberFormat.Integer)
10993
+ ).addOption(
10994
+ new Option(
10995
+ "--language <pl|en|default>",
10996
+ "Built-in labels (close, errors): `pl`, `en` or `default` (= the page language)."
10997
+ ).choices(["pl", "en", "default"])
10998
+ ).option(
10999
+ "--copy <json|file>",
11000
+ "Headline, text, button and image.",
11001
+ parseJsonObjectFileOrInline("--copy")
11002
+ ).option(
11003
+ "--content <json|file>",
11004
+ "What the pop-up holds: a signup form.",
11005
+ parseJsonObjectFileOrInline("--content")
11006
+ ).option("--design <json|file>", "design", parseJsonObjectFileOrInline("--design")).option(
11007
+ "--trigger <json|file>",
11008
+ "When it opens, per device.",
11009
+ parseJsonObjectFileOrInline("--trigger")
11010
+ ).option(
11011
+ "--targeting <json|file>",
11012
+ "Where and for whom.",
11013
+ parseJsonObjectFileOrInline("--targeting")
11014
+ ).option(
11015
+ "--frequency <json|file>",
11016
+ "How often one visitor sees it; never again after a signup. Default every 7 days.",
11017
+ parseJsonObjectFileOrInline("--frequency")
11018
+ ).option(
11019
+ "--schedule <json|file>",
11020
+ "From / to (applied within a few minutes).",
11021
+ parseJsonObjectFileOrInline("--schedule")
11022
+ ).action(async (id, options, command) => {
11023
+ const flags = getGlobalFlags(command);
11024
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
11025
+ const params = {
11026
+ popupId: id
11027
+ };
11028
+ const payload = {
11029
+ name: options.name,
11030
+ priority: options.priority,
11031
+ language: options.language,
11032
+ copy: options.copy,
11033
+ content: options.content,
11034
+ design: options.design,
11035
+ trigger: options.trigger,
11036
+ targeting: options.targeting,
11037
+ frequency: options.frequency,
11038
+ schedule: options.schedule
11039
+ };
11040
+ const result = await client.call("PATCH", "/popups/:popupId", params, void 0, payload);
11041
+ emit(flags, result ?? {}, () => printJson(result ?? {}));
11042
+ });
11043
+ popups.command("status").summary("Activate or pause a pop-up").description(
11044
+ "Activates or pauses a pop-up. Activation needs a title, a button text and an existing signup form (400 popup-incomplete / 404 form-not-found), the pop-ups feature on the plan (403) and a free slot: at most 20 active pop-ups (409 too-many-active-popups). Visitors see it after their cookie decision, by its trigger, once per page view."
11045
+ ).argument("<id>", "Pop-up id (`popup_\u2026`) from list-popups.").argument(
11046
+ "<status>",
11047
+ "`active` shows it on the site (within a few minutes), `paused` takes it off."
11048
+ ).action(async (id, status, _options, command) => {
11049
+ const flags = getGlobalFlags(command);
11050
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
11051
+ const params = {
11052
+ popupId: id
11053
+ };
11054
+ const payload = {
11055
+ status
11056
+ };
11057
+ const result = await client.call(
11058
+ "POST",
11059
+ "/popups/:popupId/status",
11060
+ params,
11061
+ void 0,
11062
+ payload
11063
+ );
11064
+ emit(flags, result ?? {}, () => printJson(result ?? {}));
11065
+ });
11066
+ popups.command("delete").summary("Delete a pop-up").description(
11067
+ "Deletes a pop-up for good; an active one leaves the site within a few minutes. Its form and the signups stay. No undo - prefer pausing."
11068
+ ).argument("<id>", "Pop-up id (`popup_\u2026`) from list-popups.").option("--confirm", "required \u2014 acknowledge that you want to deletes the pop-up for good").action(async (id, options, command) => {
11069
+ const flags = getGlobalFlags(command);
11070
+ requireConfirm(options.confirm, "deletes the pop-up for good");
11071
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
11072
+ const params = {
11073
+ popupId: id
11074
+ };
11075
+ const result = await client.call("DELETE", "/popups/:popupId", params, void 0, void 0);
11076
+ emit(flags, result ?? {}, () => printJson(result ?? {}));
11077
+ });
11078
+ }
11079
+
10702
11080
  // src/commands/_generated/index.ts
10703
11081
  function registerGeneratedCommands(program2) {
10704
11082
  registerCertificatesCommands(program2);
10705
11083
  registerBlogCommands(program2);
11084
+ registerSiteRedirectsCommands(program2);
11085
+ registerPopupsCommands(program2);
10706
11086
  }
10707
11087
 
10708
11088
  // src/commands/ads/index.ts
@@ -11326,7 +11706,8 @@ async function runWhoami(command) {
11326
11706
  workspaceName: stored?.workspaceName ?? null,
11327
11707
  userEmail: stored?.userEmail ?? null,
11328
11708
  uid: claims.subject ?? null,
11329
- scopes: ["communities:read", "communities:write"],
11709
+ scopes: memberKeyScopes(claims),
11710
+ readOnly: isReadOnlyMemberKey(claims),
11330
11711
  communityApiUrl: resolveCommunityApiUrl()
11331
11712
  };
11332
11713
  emit(flags, info2, () => {
@@ -11340,7 +11721,7 @@ async function runWhoami(command) {
11340
11721
  `);
11341
11722
  else if (info2.uid) process.stdout.write(`User id: ${info2.uid}
11342
11723
  `);
11343
- process.stdout.write(`Scopes: ${info2.scopes.join(", ")}
11724
+ process.stdout.write(`Scopes: ${memberScopeLabel(claims)}
11344
11725
  `);
11345
11726
  process.stdout.write(`Community API: ${info2.communityApiUrl ?? "<unresolved>"}
11346
11727
  `);
@@ -11396,10 +11777,15 @@ function registerAuthCommands(program2) {
11396
11777
  process.stdout.write(` status: no credentials file found
11397
11778
  `);
11398
11779
  } else {
11780
+ const storedClaims = decodeTokenClaims(stored.apiKey);
11399
11781
  process.stdout.write(` source: ${stored.source ?? "manual"}
11400
11782
  `);
11401
- process.stdout.write(` kind : ${stored.kind ?? decodeTokenKind(stored.apiKey)}
11783
+ process.stdout.write(` kind : ${stored.kind ?? storedClaims.kind}
11402
11784
  `);
11785
+ if (storedClaims.kind === "member") {
11786
+ process.stdout.write(` scope : ${memberScopeLabel(storedClaims)}
11787
+ `);
11788
+ }
11403
11789
  process.stdout.write(` saved : ${stored.savedAt}
11404
11790
  `);
11405
11791
  if (stored.userEmail) {
@@ -11437,6 +11823,8 @@ Resolved by next call:
11437
11823
  process.stdout.write(` kind : ${kind}
11438
11824
  `);
11439
11825
  if (kind === "member") {
11826
+ process.stdout.write(` scope : ${memberScopeLabel(decodeTokenClaims(apiKey))}
11827
+ `);
11440
11828
  process.stdout.write(
11441
11829
  ` community API: ${resolveCommunityApiUrl() ?? "<unresolved \u2014 set --api-url>"}
11442
11830
  `
@@ -11452,7 +11840,8 @@ Resolved by next call:
11452
11840
  "--api-url <url>",
11453
11841
  "API URL to associate with this key (for member keys, the api-community URL)"
11454
11842
  ).action((key, options) => {
11455
- const kind = decodeTokenKind(key);
11843
+ const claims = decodeTokenClaims(key);
11844
+ const { kind } = claims;
11456
11845
  const path2 = writeCredentials({
11457
11846
  apiKey: key,
11458
11847
  apiUrl: options.apiUrl,
@@ -11460,7 +11849,8 @@ Resolved by next call:
11460
11849
  source: "manual",
11461
11850
  kind
11462
11851
  });
11463
- process.stdout.write(`Saved ${kind === "member" ? "member " : ""}API key to ${path2}
11852
+ const label = kind === "member" ? isReadOnlyMemberKey(claims) ? "read-only member " : "member " : "";
11853
+ process.stdout.write(`Saved ${label}API key to ${path2}
11464
11854
  `);
11465
11855
  if (kind === "member" && !options.apiUrl) {
11466
11856
  process.stdout.write(
@@ -11765,6 +12155,17 @@ async function runBrowserAuth(options, entryUrl) {
11765
12155
  server.close();
11766
12156
  }
11767
12157
  }
12158
+ function buildMemberConsentParams(input) {
12159
+ return {
12160
+ redirect_uri: input.redirectUri,
12161
+ state: input.state,
12162
+ code_challenge: input.challenge,
12163
+ code_challenge_method: "S256",
12164
+ hostname: input.hostname,
12165
+ client: "zanfia-cli",
12166
+ ...input.readOnly ? { read_only: "1" } : null
12167
+ };
12168
+ }
11768
12169
  function resolveMemberExchangeUrl() {
11769
12170
  const explicit = process.env.ZANFIA_MEMBER_EXCHANGE_URL ?? backendDefaults.memberExchangeUrl;
11770
12171
  if (explicit) return explicit;
@@ -11809,14 +12210,16 @@ async function runMemberLogin(options) {
11809
12210
  const host = safeHostname();
11810
12211
  const server = await startLoopbackServer();
11811
12212
  const redirectUri = `http://127.0.0.1:${server.port}${CALLBACK_PATH}`;
11812
- const url = buildConsentUrl(consentUrl, {
11813
- redirect_uri: redirectUri,
11814
- state,
11815
- code_challenge: challenge,
11816
- code_challenge_method: "S256",
11817
- hostname: host,
11818
- client: "zanfia-cli"
11819
- });
12213
+ const url = buildConsentUrl(
12214
+ consentUrl,
12215
+ buildMemberConsentParams({
12216
+ redirectUri,
12217
+ state,
12218
+ challenge,
12219
+ hostname: host,
12220
+ readOnly: options.readOnly
12221
+ })
12222
+ );
11820
12223
  process.stdout.write(`Opening ${url}
11821
12224
  `);
11822
12225
  process.stdout.write("Waiting for browser callback...\n\n");
@@ -11842,6 +12245,8 @@ async function runMemberLogin(options) {
11842
12245
  workspaceName: exchanged.workspaceName
11843
12246
  });
11844
12247
  process.stdout.write(`Logged in as ${exchanged.userEmail} (community member).
12248
+ `);
12249
+ process.stdout.write(`Access: ${memberScopeLabel(decodeTokenClaims(exchanged.token))}
11845
12250
  `);
11846
12251
  process.stdout.write(`Workspace: ${exchanged.workspaceName} (${exchanged.workspaceId})
11847
12252
  `);
@@ -11873,6 +12278,9 @@ function registerLoginCommand(auth) {
11873
12278
  ).option(
11874
12279
  "--address <url>",
11875
12280
  "sign in as a community member (Community API) against this creator platform URL"
12281
+ ).option(
12282
+ "--read-only",
12283
+ "member login only: the key can read the communities but never post, comment or chat"
11876
12284
  ).option("-v, --verbose", "show HTTP request details").addHelpText(
11877
12285
  "after",
11878
12286
  `
@@ -11888,24 +12296,33 @@ The two flows use different consent pages:
11888
12296
  command uses another stored login just for that command.
11889
12297
 
11890
12298
  Community member login \u2014 Community API only:
11891
- login --address https://<creator-platform-url>
12299
+ login --address https://<creator-platform-url> [--read-only]
11892
12300
  Opens the consent page on that creator's platform (where you log in as
11893
12301
  their customer). The CLI gets a member token scoped to that workspace's
11894
12302
  communities; the community URL is passed as the platform address, and
11895
- which community to act in is chosen per command.
12303
+ which community to act in is chosen per command. --read-only gets a key
12304
+ that can read and summarize but never post, comment or chat (the right
12305
+ choice for an agent that only reads); \`auth status\` shows the scope.
11896
12306
 
11897
12307
  No browser? Generate a key on the creator's platform under
11898
- Settings -> Developer and paste the shown "auth set-key" command instead.
12308
+ Settings -> AI agents and paste the shown "auth set-key"
12309
+ command instead.
11899
12310
  `
11900
12311
  ).action(async (options) => {
11901
12312
  if (options.address) {
11902
12313
  await runMemberLogin({
11903
12314
  address: options.address,
11904
12315
  apiUrl: options.apiUrl,
11905
- verbose: options.verbose
12316
+ verbose: options.verbose,
12317
+ readOnly: options.readOnly
11906
12318
  });
11907
12319
  return;
11908
12320
  }
12321
+ if (options.readOnly) {
12322
+ throw new Error(
12323
+ "--read-only applies to community member logins: add --address <creator-platform-url> (or use `zanfia join <handle> --read-only`)."
12324
+ );
12325
+ }
11909
12326
  await runLogin(options);
11910
12327
  });
11911
12328
  }
@@ -12816,10 +13233,10 @@ function registerCampaignsCommands(program2) {
12816
13233
  });
12817
13234
  });
12818
13235
  campaigns.command("test").description(
12819
- "Send a TEST of the saved campaign to up to 3 addresses (default: your own) \u2014 subject prefixed [Test], sample personalization values; never the audience"
13236
+ "Send a TEST of the saved campaign to your team's addresses only (default: your own) \u2014 subject prefixed [Test], sample personalization values; never the audience"
12820
13237
  ).argument("<id>", "campaign id").option(
12821
13238
  "--to <email>",
12822
- "test recipient \u2014 repeatable or comma-separated, max 3 (default: your own address)",
13239
+ "test recipient: a team member account e-mail (or a mail-tester.com inbox), repeatable or comma-separated, max 3 (default: your own address)",
12823
13240
  collectRepeatable,
12824
13241
  []
12825
13242
  ).action(async (id, options, command) => {
@@ -13305,7 +13722,8 @@ var CREDENTIAL_PAYMENT_GATEWAYS = [
13305
13722
  "przelewy24",
13306
13723
  "paynow",
13307
13724
  "paypal",
13308
- "dodo"
13725
+ "dodo",
13726
+ "tubapay"
13309
13727
  ];
13310
13728
  var COMMUNITY_EVENT_LOCATION_TYPES = [
13311
13729
  "online",
@@ -14176,6 +14594,33 @@ Next page: --cursor ${page.nextCursor}
14176
14594
  process.stdout.write(` Previous emails: ${detail.previousEmails.join(", ")}
14177
14595
  `);
14178
14596
  }
14597
+ const customFields = Object.entries(detail.customFields ?? {});
14598
+ if (customFields.length > 0) {
14599
+ process.stdout.write(" Custom fields:\n");
14600
+ for (const [key, value] of customFields) {
14601
+ process.stdout.write(` ${key}: ${String(value)}
14602
+ `);
14603
+ }
14604
+ }
14605
+ });
14606
+ });
14607
+ clients2.command("fields").description(
14608
+ "List the custom contact fields (key, name, type, options); set values with `clients update --field key=value`"
14609
+ ).option("--include-archived", "also list archived fields (their values are read-only)").action(async (options, command) => {
14610
+ const flags = getGlobalFlags(command);
14611
+ const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
14612
+ const result = await client.listClientCustomFields(options.includeArchived === true);
14613
+ emit(flags, result, () => {
14614
+ printTable(
14615
+ result.fields.map((field) => ({
14616
+ key: field.key,
14617
+ name: field.name,
14618
+ type: field.type,
14619
+ options: field.options.filter((option) => !option.archived).map((option) => `${option.key}=${option.label}`).join(", "),
14620
+ archived: field.archived ? "yes" : ""
14621
+ })),
14622
+ ["key", "name", "type", "options", "archived"]
14623
+ );
14179
14624
  });
14180
14625
  });
14181
14626
  registerClientTagsCommands(clients2);
@@ -14289,12 +14734,27 @@ Next page: --cursor ${page.nextCursor}
14289
14734
  `);
14290
14735
  });
14291
14736
  });
14292
- clients2.command("update").description("Update a client's profile (name, phone, language)").argument("<id>", "workspace client id (wcid)").option("--first-name <name>", "new first name").option("--last-name <name>", "new last name").option("--phone <number>", "new phone number").option("--language <code>", "new preferred language code (e.g. en, pl)").action(
14737
+ clients2.command("update").description("Update a client's profile (name, phone, language) and custom field values").argument("<id>", "workspace client id (wcid)").option("--first-name <name>", "new first name").option("--last-name <name>", "new last name").option("--phone <number>", "new phone number").option("--language <code>", "new preferred language code (e.g. en, pl)").option(
14738
+ "--field <key=value>",
14739
+ "set a custom field value (repeatable; keys from `clients fields`, e.g. --field plan=premium)",
14740
+ collectRepeatable2,
14741
+ []
14742
+ ).option("--clear-field <key>", "clear a custom field value (repeatable)", collectRepeatable2, []).action(
14293
14743
  async (id, options, command) => {
14294
14744
  const flags = getGlobalFlags(command);
14295
- if (options.firstName === void 0 && options.lastName === void 0 && options.phone === void 0 && options.language === void 0) {
14745
+ const customFields = {};
14746
+ for (const entry of options.field) {
14747
+ const separator = entry.indexOf("=");
14748
+ if (separator <= 0) {
14749
+ throw new Error(`Invalid --field "${entry}": use key=value.`);
14750
+ }
14751
+ customFields[entry.slice(0, separator).trim()] = entry.slice(separator + 1);
14752
+ }
14753
+ for (const key of options.clearField) customFields[key.trim()] = null;
14754
+ const hasCustomFields = Object.keys(customFields).length > 0;
14755
+ if (options.firstName === void 0 && options.lastName === void 0 && options.phone === void 0 && options.language === void 0 && !hasCustomFields) {
14296
14756
  throw new Error(
14297
- "Nothing to update \u2014 pass at least one of --first-name, --last-name, --phone, --language."
14757
+ "Nothing to update \u2014 pass at least one of --first-name, --last-name, --phone, --language, --field, --clear-field."
14298
14758
  );
14299
14759
  }
14300
14760
  const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
@@ -14302,7 +14762,8 @@ Next page: --cursor ${page.nextCursor}
14302
14762
  firstName: options.firstName,
14303
14763
  lastName: options.lastName,
14304
14764
  phoneNumber: options.phone,
14305
- language: options.language
14765
+ language: options.language,
14766
+ ...hasCustomFields ? { customFields } : {}
14306
14767
  });
14307
14768
  emit(flags, result, () => {
14308
14769
  process.stdout.write(`Updated client ${result.clientId}.
@@ -18670,7 +19131,7 @@ function printOverview(overview) {
18670
19131
  const p = overview.payments;
18671
19132
  const on = (value) => value ? "on" : "off";
18672
19133
  process.stdout.write(
18673
- `Payments: stripe=${on(p.stripe)} payU=${on(p.payU)} tpay=${on(p.tpay)} payNow=${on(p.payNow)} przelewy24=${on(p.przelewy24)} paypal=${on(p.paypal)} dodo=${on(p.dodo)} manual=${p.manual ? `on (${p.manual.name})` : "off"}
19134
+ `Payments: stripe=${on(p.stripe)} payU=${on(p.payU)} tpay=${on(p.tpay)} payNow=${on(p.payNow)} przelewy24=${on(p.przelewy24)} paypal=${on(p.paypal)} dodo=${on(p.dodo)} tubapay=${on(p.tubapay)} manual=${p.manual ? `on (${p.manual.name})` : "off"}
18674
19135
  `
18675
19136
  );
18676
19137
  }
@@ -18945,7 +19406,7 @@ function readSecret2(label, value, fromStdin, fromEnv) {
18945
19406
  function printPayments(payments) {
18946
19407
  const on = (value) => value ? "on" : "off";
18947
19408
  process.stdout.write(
18948
- `Payments: stripe=${on(payments.stripe)} payu=${on(payments.payU)} tpay=${on(payments.tpay)} paynow=${on(payments.payNow)} przelewy24=${on(payments.przelewy24)} paypal=${on(payments.paypal)} dodo=${on(payments.dodo)} manual=${payments.manual ? "on" : "off"}
19409
+ `Payments: stripe=${on(payments.stripe)} payu=${on(payments.payU)} tpay=${on(payments.tpay)} paynow=${on(payments.payNow)} przelewy24=${on(payments.przelewy24)} paypal=${on(payments.paypal)} dodo=${on(payments.dodo)} tubapay=${on(payments.tubapay)} manual=${payments.manual ? "on" : "off"}
18949
19410
  `
18950
19411
  );
18951
19412
  }
@@ -19024,6 +19485,11 @@ function buildGatewayInput(gateway, o) {
19024
19485
  case "dodo":
19025
19486
  input.apiKey = secret(o.apiKey, "--api-key");
19026
19487
  break;
19488
+ case "tubapay":
19489
+ input.clientId = need(o.clientId, "--client-id");
19490
+ input.clientSecret = secret(o.clientSecret, "--client-secret");
19491
+ input.callbackSecret = secret(o.callbackSecret, "--callback-secret");
19492
+ break;
19027
19493
  }
19028
19494
  return input;
19029
19495
  }
@@ -19064,11 +19530,11 @@ function registerIntegrationProviderCommands(integrations) {
19064
19530
  }
19065
19531
  );
19066
19532
  const payments = integrations.command("payments").description(
19067
- "Credential payment gateways: payu, tpay, przelewy24 (p24), paynow, paypal, dodo. Stripe connects in the dashboard (OAuth); the transfer method is `integrations manual-payment`."
19533
+ "Credential payment gateways: payu, tpay, przelewy24 (p24), paynow, paypal, dodo, tubapay. Stripe connects in the dashboard (OAuth); the transfer method is `integrations manual-payment`."
19068
19534
  );
19069
19535
  payments.command("connect <gateway>").description(
19070
19536
  "Connect a gateway \u2014 credentials are verified with the gateway first. With --secrets-env every secret flag takes an environment variable NAME instead of the value."
19071
- ).requiredOption("--name <name>", "creator-facing label").option("--pos-id <id>", "payu / tpay / przelewy24").option("--client-id <id>", "payu / tpay / paypal").option("--client-secret <secret>", "payu / tpay / paypal").option("--second-key <key>", "payu: the second (MD5) key").option("--safety-key <key>", "tpay: the security key").option("--api-key <key>", "przelewy24 / paynow / dodo").option("--signature-key <key>", "paynow").option("--merchant-id <id>", "przelewy24").option("--crc-key <key>", "przelewy24").option("--secrets-env", "treat every secret flag value as an environment variable name").action(async (gatewayArg, options, command) => {
19537
+ ).requiredOption("--name <name>", "creator-facing label").option("--pos-id <id>", "payu / tpay / przelewy24").option("--client-id <id>", "payu / tpay / paypal; tubapay: the Partner ID").option("--client-secret <secret>", "payu / tpay / paypal / tubapay").option("--second-key <key>", "payu: the second (MD5) key").option("--safety-key <key>", "tpay: the security key").option("--api-key <key>", "przelewy24 / paynow / dodo").option("--signature-key <key>", "paynow").option("--merchant-id <id>", "przelewy24").option("--crc-key <key>", "przelewy24").option("--callback-secret <key>", "tubapay: the key TubaPay signs its notifications with").option("--secrets-env", "treat every secret flag value as an environment variable name").action(async (gatewayArg, options, command) => {
19072
19538
  const flags = getGlobalFlags(command);
19073
19539
  const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
19074
19540
  const status = await client.connectPaymentGateway(
@@ -19562,7 +20028,13 @@ async function runJoin(handleInput, options) {
19562
20028
  completed = await postJson2(
19563
20029
  "Join",
19564
20030
  joinUrl(communityApiUrl, handle, "complete"),
19565
- { email, code, firstName, hostname: hostname3 },
20031
+ {
20032
+ email,
20033
+ code,
20034
+ firstName,
20035
+ hostname: hostname3,
20036
+ ...options.readOnly ? { readOnly: true } : {}
20037
+ },
19566
20038
  { verbose }
19567
20039
  );
19568
20040
  } catch (err) {
@@ -19585,11 +20057,14 @@ async function runJoin(handleInput, options) {
19585
20057
  workspaceName: completed.workspaceName,
19586
20058
  kind: "member"
19587
20059
  });
20060
+ const claims = decodeTokenClaims(completed.token);
20061
+ const readOnly = isReadOnlyMemberKey(claims);
19588
20062
  if (options.json) {
19589
20063
  process.stdout.write(
19590
20064
  `${JSON.stringify(
19591
20065
  {
19592
20066
  joined: true,
20067
+ readOnly,
19593
20068
  alreadyMember: completed.alreadyMember,
19594
20069
  communityId: completed.communityId,
19595
20070
  communityName: completed.communityName,
@@ -19607,12 +20082,13 @@ async function runJoin(handleInput, options) {
19607
20082
  );
19608
20083
  return;
19609
20084
  }
19610
- const intro = completed.introChannelId ? ` zanfia communities post create ${completed.communityId} ${completed.introChannelId} --content "Hi, I'm <your agent>. I ..."
20085
+ const intro = completed.introChannelId && !readOnly ? ` zanfia communities post create ${completed.communityId} ${completed.introChannelId} --content "Hi, I'm <your agent>. I ..."
19611
20086
  ` : "";
19612
20087
  process.stdout.write(
19613
20088
  `
19614
20089
  ${completed.alreadyMember ? "Welcome back to" : "You are in:"} ${completed.communityName}.
19615
20090
  Member key saved to ${path2} (expires ${completed.expiresAt.slice(0, 10)}).
20091
+ Access: ${memberScopeLabel(claims)}
19616
20092
 
19617
20093
  Next:
19618
20094
  zanfia communities list
@@ -19625,17 +20101,20 @@ Plug in your agent: ${AGENT_DOCS_URL}
19625
20101
  );
19626
20102
  }
19627
20103
  function registerJoinCommand(program2) {
19628
- program2.command("join <handle>").description("Join a public community from the terminal (emailed code) and get a member key").option("--email <email>", "email to join with (prompted when omitted)").option("--name <name>", "your display name (prompted when omitted)").option("--code <code>", "the 6-digit code from the email (prompted when omitted)").addHelpText(
20104
+ program2.command("join <handle>").description("Join a public community from the terminal (emailed code) and get a member key").option("--email <email>", "email to join with (prompted when omitted)").option("--name <name>", "your display name (prompted when omitted)").option("--code <code>", "the 6-digit code from the email (prompted when omitted)").option("--read-only", "get a key that can read and summarize but never post, comment or chat").addHelpText(
19629
20105
  "after",
19630
20106
  `
19631
20107
  Examples:
19632
20108
  zanfia join crew-of-one
19633
20109
  zanfia join crew-of-one --email me@example.com --name "Sam" --code 123456
20110
+ zanfia join crew-of-one --read-only
19634
20111
 
19635
20112
  The key is a MEMBER key: it reaches the Community API for that creator's
19636
- communities only (read/post/comment/chat), never your own workspace. It is
19637
- saved to ~/.config/zanfia/credentials.json and expires in 90 days \u2014 run
19638
- join again to refresh it.
20113
+ communities only (read/post/comment/chat), never your own workspace. With
20114
+ --read-only it can only read (the right choice for an agent that reads and
20115
+ summarizes); \`zanfia auth status\` shows the scope. It is saved to
20116
+ ~/.config/zanfia/credentials.json and expires in 90 days \u2014 run join again
20117
+ to refresh it.
19639
20118
  `
19640
20119
  ).action(async (handle, options, command) => {
19641
20120
  const globals = getGlobalFlags(command);
@@ -19646,15 +20125,28 @@ join again to refresh it.
19646
20125
  // src/commands/liveRooms/index.ts
19647
20126
  var minutes = (seconds) => `${Math.round(seconds / 60)} min`;
19648
20127
  var percent = (part, whole) => whole > 0 ? `${Math.round(part / whole * 100)}%` : "-";
20128
+ var countOrDash = (value) => value === null || value === void 0 ? "-" : String(value);
19649
20129
  var WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
20130
+ function describeExclusions(schedule) {
20131
+ const parts = [];
20132
+ if (schedule.kind !== "daily" && schedule.nightWindow) {
20133
+ parts.push(`none ${schedule.nightWindow.from}-${schedule.nightWindow.to}`);
20134
+ }
20135
+ if (schedule.blackoutDates && schedule.blackoutDates.length > 0) {
20136
+ const days = schedule.blackoutDates.map((range) => range.from === range.to ? range.from : `${range.from}..${range.to}`).join(", ");
20137
+ parts.push(`none on ${days}`);
20138
+ }
20139
+ return parts.length > 0 ? `; ${parts.join("; ")}` : "";
20140
+ }
19650
20141
  function describeSchedule(room) {
19651
20142
  if (!room.schedule) return "fixed";
19652
20143
  const until = room.schedule.until ? ` until ${room.schedule.until}` : "";
20144
+ const exclusions = describeExclusions(room.schedule);
19653
20145
  if (room.schedule.kind === "daily") {
19654
20146
  const days = room.schedule.weekdays ? room.schedule.weekdays.map((day) => WEEKDAYS[day - 1] ?? String(day)).join(", ") : "daily";
19655
- return `${days} at ${room.schedule.times.join(", ")} (${room.timezone})${until}`;
20147
+ return `${days} at ${room.schedule.times.join(", ")} (${room.timezone})${until}${exclusions}`;
19656
20148
  }
19657
- return `every ${room.schedule.everyMinutes} min${until}`;
20149
+ return `every ${room.schedule.everyMinutes} min${until}${exclusions}`;
19658
20150
  }
19659
20151
  function registerLiveRoomsCommands(program2) {
19660
20152
  const liveRooms = program2.command("live-rooms").description(
@@ -19687,6 +20179,7 @@ function registerLiveRoomsCommands(program2) {
19687
20179
  printTable(
19688
20180
  result.sessions.map((session) => ({
19689
20181
  session: session.sessionStartAt,
20182
+ registered: countOrDash(session.registered),
19690
20183
  attendees: session.attendees,
19691
20184
  identified: session.identified,
19692
20185
  avgWatched: `${minutes(session.averageWatchedSeconds)} (${percent(
@@ -19695,10 +20188,29 @@ function registerLiveRoomsCommands(program2) {
19695
20188
  )})`,
19696
20189
  toEnd: `${session.watchedToEnd} (${percent(session.watchedToEnd, session.attendees)})`,
19697
20190
  sawOffer: session.sawOffer,
19698
- clickedOffer: session.clickedOffer
20191
+ clickedOffer: session.clickedOffer,
20192
+ bought: countOrDash(session.purchased)
19699
20193
  })),
19700
- ["session", "attendees", "identified", "avgWatched", "toEnd", "sawOffer", "clickedOffer"]
20194
+ [
20195
+ "session",
20196
+ "registered",
20197
+ "attendees",
20198
+ "identified",
20199
+ "avgWatched",
20200
+ "toEnd",
20201
+ "sawOffer",
20202
+ "clickedOffer",
20203
+ "bought"
20204
+ ]
19701
20205
  );
20206
+ const totals = result.totals;
20207
+ if (totals) {
20208
+ process.stdout.write(
20209
+ `
20210
+ Room total (${totals.sessions} started sessions): registered ${countOrDash(totals.registered)} \u2192 attended ${totals.attendees} \u2192 saw the offer ${totals.sawOffer} \u2192 clicked ${totals.clickedOffer} \u2192 bought ${countOrDash(totals.purchased)}${totals.capped ? " (at least: a read hit its cap)" : ""}
20211
+ `
20212
+ );
20213
+ }
19702
20214
  if (options.session !== void 0) {
19703
20215
  process.stdout.write(`
19704
20216
  Viewers of ${options.session}:
@@ -19729,7 +20241,7 @@ import { basename } from "path";
19729
20241
  import { createReadStream as createReadStream2 } from "fs";
19730
20242
  import { stat as stat2 } from "fs/promises";
19731
20243
 
19732
- // ../../node_modules/tus-js-client/lib.esm/error.js
20244
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/error.js
19733
20245
  function _typeof(o) {
19734
20246
  "@babel/helpers - typeof";
19735
20247
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
@@ -19883,14 +20395,14 @@ var DetailedError = /* @__PURE__ */ (function(_Error) {
19883
20395
  })(/* @__PURE__ */ _wrapNativeSuper(Error));
19884
20396
  var error_default = DetailedError;
19885
20397
 
19886
- // ../../node_modules/tus-js-client/lib.esm/logger.js
20398
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/logger.js
19887
20399
  var isEnabled = false;
19888
20400
  function log(msg) {
19889
20401
  if (!isEnabled) return;
19890
20402
  console.log(msg);
19891
20403
  }
19892
20404
 
19893
- // ../../node_modules/tus-js-client/lib.esm/noopUrlStorage.js
20405
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/noopUrlStorage.js
19894
20406
  function _typeof2(o) {
19895
20407
  "@babel/helpers - typeof";
19896
20408
  return _typeof2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
@@ -19960,7 +20472,7 @@ var NoopUrlStorage = /* @__PURE__ */ (function() {
19960
20472
  }]);
19961
20473
  })();
19962
20474
 
19963
- // ../../node_modules/js-base64/base64.mjs
20475
+ // ../../../Zanfia2/node_modules/tus-js-client/node_modules/js-base64/base64.mjs
19964
20476
  var version = "3.7.8";
19965
20477
  var VERSION = version;
19966
20478
  var _hasBuffer = typeof Buffer === "function";
@@ -20122,10 +20634,10 @@ var gBase64 = {
20122
20634
  extendBuiltins
20123
20635
  };
20124
20636
 
20125
- // ../../node_modules/tus-js-client/lib.esm/upload.js
20637
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/upload.js
20126
20638
  var import_url_parse = __toESM(require_url_parse());
20127
20639
 
20128
- // ../../node_modules/tus-js-client/lib.esm/uuid.js
20640
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/uuid.js
20129
20641
  function uuid() {
20130
20642
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
20131
20643
  var r = Math.random() * 16 | 0;
@@ -20134,7 +20646,7 @@ function uuid() {
20134
20646
  });
20135
20647
  }
20136
20648
 
20137
- // ../../node_modules/tus-js-client/lib.esm/upload.js
20649
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/upload.js
20138
20650
  function _regeneratorRuntime() {
20139
20651
  "use strict";
20140
20652
  _regeneratorRuntime = function _regeneratorRuntime4() {
@@ -21369,11 +21881,11 @@ function splitSizeIntoParts(totalSize, partCount) {
21369
21881
  BaseUpload.defaultOptions = defaultOptions;
21370
21882
  var upload_default = BaseUpload;
21371
21883
 
21372
- // ../../node_modules/tus-js-client/lib.esm/node/fileReader.js
21884
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/node/fileReader.js
21373
21885
  var import_is_stream = __toESM(require_is_stream());
21374
21886
  import { ReadStream } from "fs";
21375
21887
 
21376
- // ../../node_modules/tus-js-client/lib.esm/node/sources/BufferSource.js
21888
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/node/sources/BufferSource.js
21377
21889
  function _typeof4(o) {
21378
21890
  "@babel/helpers - typeof";
21379
21891
  return _typeof4 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
@@ -21440,7 +21952,7 @@ var BufferSource = /* @__PURE__ */ (function() {
21440
21952
  }]);
21441
21953
  })();
21442
21954
 
21443
- // ../../node_modules/tus-js-client/lib.esm/node/sources/FileSource.js
21955
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/node/sources/FileSource.js
21444
21956
  import { createReadStream, promises as fsPromises } from "fs";
21445
21957
  function _typeof5(o) {
21446
21958
  "@babel/helpers - typeof";
@@ -21816,7 +22328,7 @@ var FileSource = /* @__PURE__ */ (function() {
21816
22328
  }]);
21817
22329
  })();
21818
22330
 
21819
- // ../../node_modules/tus-js-client/lib.esm/node/sources/StreamSource.js
22331
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/node/sources/StreamSource.js
21820
22332
  function _typeof6(o) {
21821
22333
  "@babel/helpers - typeof";
21822
22334
  return _typeof6 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
@@ -22256,7 +22768,7 @@ var StreamSource = /* @__PURE__ */ (function() {
22256
22768
  }]);
22257
22769
  })();
22258
22770
 
22259
- // ../../node_modules/tus-js-client/lib.esm/node/fileReader.js
22771
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/node/fileReader.js
22260
22772
  function _typeof7(o) {
22261
22773
  "@babel/helpers - typeof";
22262
22774
  return _typeof7 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
@@ -22324,7 +22836,7 @@ var FileReader = /* @__PURE__ */ (function() {
22324
22836
  }]);
22325
22837
  })();
22326
22838
 
22327
- // ../../node_modules/tus-js-client/lib.esm/node/fileSignature.js
22839
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/node/fileSignature.js
22328
22840
  import { createHash as createHash3 } from "crypto";
22329
22841
  import * as fs from "fs";
22330
22842
  import * as path from "path";
@@ -22352,7 +22864,7 @@ function fingerprint(file, options) {
22352
22864
  return Promise.resolve(null);
22353
22865
  }
22354
22866
 
22355
- // ../../node_modules/tus-js-client/lib.esm/node/httpStack.js
22867
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/node/httpStack.js
22356
22868
  var import_lodash = __toESM(require_lodash());
22357
22869
  import * as http from "http";
22358
22870
  import * as https from "https";
@@ -22656,11 +23168,11 @@ var writeBufferToStreamWithProgress = function writeBufferToStreamWithProgress2(
22656
23168
  writeNextChunk();
22657
23169
  };
22658
23170
 
22659
- // ../../node_modules/tus-js-client/lib.esm/node/urlStorage.js
23171
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/node/urlStorage.js
22660
23172
  var import_combine_errors = __toESM(require_combine_errors());
22661
23173
  var lockfile = __toESM(require_proper_lockfile());
22662
23174
 
22663
- // ../../node_modules/tus-js-client/lib.esm/node/index.js
23175
+ // ../../../Zanfia2/node_modules/tus-js-client/lib.esm/node/index.js
22664
23176
  function _typeof9(o) {
22665
23177
  "@babel/helpers - typeof";
22666
23178
  return _typeof9 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
@@ -25327,7 +25839,10 @@ function registerPagesCommands(program2) {
25327
25839
  });
25328
25840
  pages.command("generate").description(
25329
25841
  "AI-generate a hosted DRAFT page from a brief. Consumes AI credits and runs in the background (202 + run id, ~1-5 minutes) \u2014 the page appears in `pages list` when the run finishes. Signup intents (lead-magnet / webinar / waitlist) also provision a signup form, a companion thank-you page and a DRAFT delivery automation. Facts in the brief (price, date, links) are used verbatim. Requires --confirm."
25330
- ).requiredOption("--intent <intent>", `what the page is for (${PAGE_INTENTS.join(" | ")})`).requiredOption("--title <title>", "page title (the slug derives from it unless --slug)").requiredOption("--brief <textOrFile>", "the brief \u2014 inline text or a path to a text file").option("--template <templateId>", "design-template seed from `pages templates`").option("--product <productId>", "grounding product (real name/prices + checkout link)").option("--checkout <checkoutId>", "override the product's default checkout as the offer").option("--form <formId>", "standalone signup form whose embed becomes the signup CTA").option("--source-url <url>", "website to start from (fetched server-side; beats --template)").option(
25842
+ ).requiredOption("--intent <intent>", `what the page is for (${PAGE_INTENTS.join(" | ")})`).requiredOption("--title <title>", "page title (the slug derives from it unless --slug)").requiredOption("--brief <textOrFile>", "the brief \u2014 inline text or a path to a text file").option("--template <templateId>", "design-template seed from `pages templates`").option("--product <productId>", "grounding product (real name/prices + checkout link)").option("--checkout <checkoutId>", "override the product's default checkout as the offer").option(
25843
+ "--form <formId>",
25844
+ "standalone signup form the page renders natively as its signup section (never an iframe)"
25845
+ ).option("--source-url <url>", "website to start from (fetched server-side; beats --template)").option(
25331
25846
  "--source-mode <mode>",
25332
25847
  `how the source site is used, required with --source-url (${SOURCE_SITE_MODES.join(" | ")})`
25333
25848
  ).option("--slug <slug>", "public URL slug; derived from the title when omitted").option(
@@ -25676,6 +26191,10 @@ function registerProductsCommands(program2) {
25676
26191
  `);
25677
26192
  if (product.storefrontVisibility) {
25678
26193
  process.stdout.write(` Visibility: ${product.storefrontVisibility}
26194
+ `);
26195
+ }
26196
+ if (product.language !== void 0) {
26197
+ process.stdout.write(` Language: ${product.language ?? "none (platform language)"}
25679
26198
  `);
25680
26199
  }
25681
26200
  process.stdout.write(` Clients: ${product.clientCount}
@@ -25695,6 +26214,10 @@ function registerProductsCommands(program2) {
25695
26214
  "--period <period>",
25696
26215
  "billing period for --amount: one_time, monthly or yearly (default one_time)"
25697
26216
  ).option("--description-file <path>", "read the product description from a file").option(
26217
+ "--language <pl|en>",
26218
+ "the product's language (buyer-facing pages and e-mails; omitted = the platform's language). Also picks the --amount currency when --currency is omitted (pl \u2192 pln, else usd)",
26219
+ parseProductLanguage
26220
+ ).option(
25698
26221
  "--cover <pathOrUrl>",
25699
26222
  "cover image: a local file (uploaded to the media library first) or an https URL"
25700
26223
  ).option(
@@ -25715,7 +26238,8 @@ function registerProductsCommands(program2) {
25715
26238
  name: options.name,
25716
26239
  productType: options.type,
25717
26240
  description,
25718
- offer
26241
+ offer,
26242
+ language: options.language
25719
26243
  });
25720
26244
  const outcome = {};
25721
26245
  try {
@@ -25764,21 +26288,28 @@ function registerProductsCommands(program2) {
25764
26288
  });
25765
26289
  }
25766
26290
  );
25767
- products2.command("update").description("Update a product's name, description and/or storefront visibility").argument("<id>", "product id").option("--name <name>", "new product name").option("--description <description>", "new product description").option(
26291
+ products2.command("update").description("Update a product's name, description, storefront visibility and/or language").argument("<id>", "product id").option("--name <name>", "new product name").option("--description <description>", "new product description").option(
25768
26292
  "--visibility <public|unlisted|private>",
25769
26293
  "where buyers find it once published: public (store + product page), unlisted (product page by link only), private (checkout links only)",
25770
26294
  parseStorefrontVisibility
26295
+ ).option(
26296
+ "--language <pl|en|none>",
26297
+ "the product's language (buyer-facing pages and e-mails); none clears it (the platform's language applies)",
26298
+ parseProductLanguageOrNone
25771
26299
  ).action(
25772
26300
  async (id, options, command) => {
25773
- if (options.name === void 0 && options.description === void 0 && options.visibility === void 0) {
25774
- throw new Error("Nothing to update: pass --name, --description and/or --visibility.");
26301
+ if (options.name === void 0 && options.description === void 0 && options.visibility === void 0 && options.language === void 0) {
26302
+ throw new Error(
26303
+ "Nothing to update: pass --name, --description, --visibility and/or --language."
26304
+ );
25775
26305
  }
25776
26306
  const flags = getGlobalFlags(command);
25777
26307
  const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
25778
26308
  const result = await client.updateProduct(id, {
25779
26309
  name: options.name,
25780
26310
  description: options.description,
25781
- storefrontVisibility: options.visibility
26311
+ storefrontVisibility: options.visibility,
26312
+ language: options.language === PRODUCT_LANGUAGE_NONE ? null : options.language
25782
26313
  });
25783
26314
  emit(flags, result, () => {
25784
26315
  process.stdout.write(`Updated product ${result.productId}
@@ -26788,7 +27319,7 @@ function buildUpdateInput2(options) {
26788
27319
  }
26789
27320
  function registerReferralsCommands(program2) {
26790
27321
  const referrals = program2.command("referrals").description(
26791
- "Referral / affiliate programs \u2014 create reward ladders over your products, enroll clients, approve or reject earned rewards, and retry failed reward deliveries"
27322
+ 'Referral programs: "Nagrody za polecenia" (kind referral, reward ladders for your customers) and "Program partnerski" (kind affiliate, partner commission), both from the Growth plan. Create programs over your products, enroll clients, approve or reject earned rewards, and retry failed reward deliveries'
26792
27323
  );
26793
27324
  referrals.command("list").description("List referral programs (kind, status, products, headline stats)").action(async (_, command) => {
26794
27325
  const flags = getGlobalFlags(command);
@@ -26887,7 +27418,7 @@ Failed deliveries (${result.failedDeliveries.length})
26887
27418
  });
26888
27419
  });
26889
27420
  referrals.command("create").description(
26890
- "Create a program over one or more products. Deep config (milestones, commission, attribution) goes in --json; flat flags win over --json keys."
27421
+ "Create a program over one or more products (both kinds need the Growth plan). Deep config (milestones, commission, attribution) goes in --json; flat flags win over --json keys."
26891
27422
  ).requiredOption("--kind <kind>", `program kind (${PROGRAM_KINDS.join(" | ")})`).requiredOption("--name <name>", "program name").requiredOption("--product <ids>", "comma-separated product ids whose purchases count").option("--enrollment <mode>", `how participants join (${ENROLLMENT_MODES.join(" | ")})`).option("--status <status>", `initial status (${WRITABLE_STATUSES.join(" | ")})`).option(
26892
27423
  "--json <fileOrJson>",
26893
27424
  "inline JSON object or .json path with `milestones`, `commission` and/or `attribution` (write it as --json=<value> \u2014 a bare --json is the global JSON-output flag)"
@@ -26902,7 +27433,7 @@ Failed deliveries (${result.failedDeliveries.length})
26902
27433
  });
26903
27434
  });
26904
27435
  referrals.command("update").description(
26905
- "Update a program. --product and --json `milestones` are FULL replaces (read the program first); flat flags win over --json keys. Use `referrals archive` to archive."
27436
+ "Update a program. --product and --json `milestones` are FULL replaces (read the program first); flat flags win over --json keys. Activating (--status active) needs the Growth plan. Use `referrals archive` to archive."
26906
27437
  ).argument("<programId>", "program id").option("--name <name>", "program name").option("--status <status>", `status (${WRITABLE_STATUSES.join(" | ")})`).option("--product <ids>", "comma-separated product ids (full replace)").option("--enrollment <mode>", `how participants join (${ENROLLMENT_MODES.join(" | ")})`).option(
26907
27438
  "--json <fileOrJson>",
26908
27439
  "inline JSON object or .json path with `milestones`, `commission` and/or `attribution` (write it as --json=<value> \u2014 a bare --json is the global JSON-output flag)"
@@ -26930,7 +27461,7 @@ Failed deliveries (${result.failedDeliveries.length})
26930
27461
  });
26931
27462
  });
26932
27463
  referrals.command("enroll").description(
26933
- "Enroll one client as a participant (idempotent \u2014 re-enrolling reports `alreadyEnrolled`). Prints the ref code the client shares."
27464
+ "Enroll one client as a participant (idempotent \u2014 re-enrolling reports `alreadyEnrolled`). Prints the ref code the client shares. Needs the Growth plan."
26934
27465
  ).argument("<programId>", "program id").requiredOption("--client <clientId>", "workspace client id (wcid)").requiredOption("--email <email>", "the client's email").option("--first-name <name>", "first name (optional)").option("--last-name <name>", "last name (optional)").action(async (programId, options, command) => {
26935
27466
  const flags = getGlobalFlags(command);
26936
27467
  const client = createApiClient({ apiKey: flags.apiKey, verbose: flags.verbose });
@@ -26949,7 +27480,7 @@ Failed deliveries (${result.failedDeliveries.length})
26949
27480
  });
26950
27481
  });
26951
27482
  referrals.command("enroll-all").description(
26952
- "Enroll EVERY client with access to one of the program products. Requires --confirm. Reports enrolled / alreadyEnrolled / skippedWithoutAccount counts."
27483
+ 'Enroll EVERY client with access to one of the program products ("Nagrody za polecenia" only: a "Program partnerski" is refused, partners join by invite link). Needs the Growth plan. Requires --confirm. Reports enrolled / alreadyEnrolled / skippedWithoutAccount counts.'
26953
27484
  ).argument("<programId>", "program id").option("--confirm", "required \u2014 acknowledge the bulk enrollment").action(async (programId, options, command) => {
26954
27485
  const flags = getGlobalFlags(command);
26955
27486
  requireConfirm13(options.confirm, `enroll all clients in program ${programId}`);
@@ -30376,8 +30907,8 @@ function applyShortHelp(program2) {
30376
30907
 
30377
30908
  // src/program.ts
30378
30909
  function resolveCliVersion() {
30379
- if ("0.9.0".length > 0) {
30380
- return "0.9.0";
30910
+ if ("0.13.1".length > 0) {
30911
+ return "0.13.1";
30381
30912
  }
30382
30913
  try {
30383
30914
  const raw = readFileSync28(new URL("../package.json", import.meta.url), "utf8");
@@ -30404,13 +30935,14 @@ Signing in \u2014 two roles, two consent pages:
30404
30935
  ${programName} login
30405
30936
  Creator (workspace) login. Opens the consent page in the Zanfia dashboard.
30406
30937
  Grants the full Workspace API: products, clients, orders, stats, \u2026
30407
- ${programName} login --address https://<creator-platform-url>
30938
+ ${programName} login --address https://<creator-platform-url> [--read-only]
30408
30939
  Community member login. Opens the consent page on that creator's platform.
30409
- Grants the Community API only: communities, posts, comments.
30940
+ Grants the Community API only: communities, posts, comments. --read-only
30941
+ gets a key that reads and summarizes but never posts.
30410
30942
  ${programName} auth set-key --api-url <api-community-url> <key>
30411
30943
  Member alternative without a browser: paste the key generated on the
30412
- creator's platform under Settings \u2192 Developer.
30413
- ${programName} join <handle>
30944
+ creator's platform under Settings \u2192 AI agents.
30945
+ ${programName} join <handle> [--read-only]
30414
30946
  Join a public community from the terminal: emailed 6-digit code, then a
30415
30947
  member key is saved \u2014 no account or browser needed. Try: join crew-of-one
30416
30948
  `