@quonfig/cli 0.0.12 → 0.0.14

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 (75) hide show
  1. package/README.md +91 -33
  2. package/dist/codegen/json-schema-to-zod.js +7 -5
  3. package/dist/codegen/language-mappers/zod-base-mapper.d.ts +2 -2
  4. package/dist/codegen/language-mappers/zod-to-string-mapper.d.ts +2 -2
  5. package/dist/codegen/language-mappers/zod-to-string-mapper.js +6 -6
  6. package/dist/codegen/language-mappers/zod-to-typescript-mapper.d.ts +2 -2
  7. package/dist/codegen/language-mappers/zod-to-typescript-mapper.js +6 -6
  8. package/dist/codegen/language-mappers/zod-to-typescript-return-value-mapper.d.ts +2 -2
  9. package/dist/codegen/language-mappers/zod-to-typescript-return-value-mapper.js +5 -5
  10. package/dist/codegen/local-config-reader.js +0 -1
  11. package/dist/codegen/schema-extractor.js +5 -2
  12. package/dist/commands/info.js +4 -1
  13. package/dist/commands/init.js +12 -2
  14. package/dist/commands/interactive.d.ts +1 -0
  15. package/dist/commands/interactive.js +8 -0
  16. package/dist/commands/login.js +9 -3
  17. package/dist/commands/migrate/doctor.js +1 -1
  18. package/dist/commands/migrate/my-code.d.ts +11 -0
  19. package/dist/commands/migrate/my-code.js +80 -0
  20. package/dist/commands/migrate/status.js +3 -16
  21. package/dist/commands/migrate.js +29 -8
  22. package/dist/commands/override.js +6 -3
  23. package/dist/commands/profile.d.ts +1 -1
  24. package/dist/commands/profile.js +1 -1
  25. package/dist/commands/pull.d.ts +2 -2
  26. package/dist/commands/pull.js +45 -47
  27. package/dist/commands/schema.d.ts +3 -3
  28. package/dist/commands/schema.js +37 -37
  29. package/dist/commands/sdk-key/create.js +12 -14
  30. package/dist/commands/sdk-key/revoke.d.ts +1 -1
  31. package/dist/commands/sdk-key/revoke.js +2 -4
  32. package/dist/commands/set-default.js +7 -5
  33. package/dist/commands/set-rollout.d.ts +1 -1
  34. package/dist/commands/set-rollout.js +16 -13
  35. package/dist/commands/sync.d.ts +3 -3
  36. package/dist/commands/sync.js +30 -26
  37. package/dist/commands/whoami.js +1 -5
  38. package/dist/commands/workspace/bootstrap.js +7 -7
  39. package/dist/commands/workspace/switch.js +2 -2
  40. package/dist/init/init-workspace.d.ts +2 -2
  41. package/dist/init/init-workspace.js +32 -18
  42. package/dist/init/samples.d.ts +1 -1
  43. package/dist/init/samples.js +2 -2
  44. package/dist/init/schema.js +24 -15
  45. package/dist/interactive-prompt.js +1 -10
  46. package/dist/migrate/doctor.js +3 -1
  47. package/dist/migrate/local-write.d.ts +26 -0
  48. package/dist/migrate/local-write.js +85 -0
  49. package/dist/migrate/migration-report.js +1 -9
  50. package/dist/migrate/push-strategy.js +1 -7
  51. package/dist/migrate/push-to-cloud.js +1 -1
  52. package/dist/migrate/sources/flagsmith.js +10 -0
  53. package/dist/quonfig.d.ts +1 -1
  54. package/dist/quonfig.js +5 -9
  55. package/dist/ui/get-value.js +1 -1
  56. package/dist/util/config-value-dto.js +17 -1
  57. package/dist/util/encryption.js +4 -1
  58. package/dist/util/friction-log.d.ts +1 -1
  59. package/dist/util/friction-log.js +5 -1
  60. package/dist/util/get-client.js +51 -3
  61. package/dist/util/get-valid-token.d.ts +4 -0
  62. package/dist/util/get-valid-token.js +17 -2
  63. package/dist/util/git-ops.js +7 -7
  64. package/dist/util/gitea-api.d.ts +2 -2
  65. package/dist/util/gitea-api.js +5 -3
  66. package/dist/util/gitea-token-storage.d.ts +2 -2
  67. package/dist/util/gitea-token-storage.js +1 -1
  68. package/dist/util/oauth-client.js +1 -1
  69. package/dist/util/token-storage.js +2 -2
  70. package/dist/verify/standalone.d.ts +0 -1
  71. package/dist/verify/standalone.js +22 -23
  72. package/dist/verify/validate.d.ts +8 -8
  73. package/dist/verify/validate.js +252 -246
  74. package/oclif.manifest.json +79 -3
  75. package/package.json +6 -6
package/README.md CHANGED
@@ -14,7 +14,7 @@ $ npm install -g @quonfig/cli
14
14
  $ qfg COMMAND
15
15
  running command...
16
16
  $ qfg (--version)
17
- @quonfig/cli/0.0.12 linux-x64 node-v24.4.1
17
+ @quonfig/cli/0.0.14 linux-x64 node-v24.4.1
18
18
  $ qfg --help [COMMAND]
19
19
  USAGE
20
20
  $ qfg COMMAND
@@ -42,6 +42,7 @@ USAGE
42
42
  * [`qfg mcp`](#qfg-mcp)
43
43
  * [`qfg migrate`](#qfg-migrate)
44
44
  * [`qfg migrate doctor`](#qfg-migrate-doctor)
45
+ * [`qfg migrate my-code`](#qfg-migrate-my-code)
45
46
  * [`qfg migrate status`](#qfg-migrate-status)
46
47
  * [`qfg override [NAME]`](#qfg-override-name)
47
48
  * [`qfg pull`](#qfg-pull)
@@ -87,7 +88,7 @@ EXAMPLES
87
88
  $ qfg config-schema --json-schema # full JSON Schema document (copy into your editor)
88
89
  ```
89
90
 
90
- _See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/config-schema.ts)_
91
+ _See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/config-schema.ts)_
91
92
 
92
93
  ## `qfg create NAME`
93
94
 
@@ -159,7 +160,7 @@ EXAMPLES
159
160
  $ qfg set-rollout my.new.flag --environment production --true-percent 20
160
161
  ```
161
162
 
162
- _See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/create.ts)_
163
+ _See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/create.ts)_
163
164
 
164
165
  ## `qfg flag info [NAME]`
165
166
 
@@ -359,7 +360,7 @@ EXAMPLES
359
360
  $ qfg generate --targets node-ts -o ./dist # combine with targets
360
361
  ```
361
362
 
362
- _See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/generate.ts)_
363
+ _See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/generate.ts)_
363
364
 
364
365
  ## `qfg generate-new-hex-key`
365
366
 
@@ -382,7 +383,7 @@ EXAMPLES
382
383
  $ qfg generate-new-hex-key
383
384
  ```
384
385
 
385
- _See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/generate-new-hex-key.ts)_
386
+ _See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/generate-new-hex-key.ts)_
386
387
 
387
388
  ## `qfg get [NAME]`
388
389
 
@@ -414,7 +415,7 @@ EXAMPLES
414
415
  $ qfg get my.config.name --environment=production
415
416
  ```
416
417
 
417
- _See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/get.ts)_
418
+ _See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/get.ts)_
418
419
 
419
420
  ## `qfg info [NAME]`
420
421
 
@@ -462,7 +463,7 @@ EXAMPLES
462
463
  $ qfg info my.config.name --exclude-evaluations # skip 24h stats
463
464
  ```
464
465
 
465
- _See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/info.ts)_
466
+ _See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/info.ts)_
466
467
 
467
468
  ## `qfg init [DIRECTORY]`
468
469
 
@@ -500,10 +501,12 @@ EXAMPLES
500
501
  $ qfg init --dry-run
501
502
  ```
502
503
 
503
- _See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/init.ts)_
504
+ _See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/init.ts)_
504
505
 
505
506
  ## `qfg interactive`
506
507
 
508
+ Launch an interactive menu to browse and manage your workspace.
509
+
507
510
  ```
508
511
  USAGE
509
512
  $ qfg interactive [--json] [--interactive] [--no-color] [--verbose]
@@ -514,11 +517,21 @@ GLOBAL FLAGS
514
517
  --no-color Do not colorize output
515
518
  --verbose Verbose output
516
519
 
520
+ DESCRIPTION
521
+ Launch an interactive menu to browse and manage your workspace.
522
+
523
+ Common shortcuts:
524
+ qfg set-default my.flag --environment production --value false # catch-all fallback
525
+ qfg set-rollout my.flag --environment production --true-percent 20 # % rollout
526
+
527
+ For arbitrary targeting rules (e.g. user.email, plan, segment, custom property),
528
+ run 'qfg config-schema' then 'qfg pull' and edit the JSON config directly.
529
+
517
530
  EXAMPLES
518
531
  $ qfg
519
532
  ```
520
533
 
521
- _See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/interactive.ts)_
534
+ _See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/interactive.ts)_
522
535
 
523
536
  ## `qfg list`
524
537
 
@@ -558,7 +571,7 @@ EXAMPLES
558
571
  $ qfg list --feature-flags
559
572
  ```
560
573
 
561
- _See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/list.ts)_
574
+ _See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/list.ts)_
562
575
 
563
576
  ## `qfg login`
564
577
 
@@ -583,7 +596,7 @@ EXAMPLES
583
596
  $ qfg login --profile myprofile
584
597
  ```
585
598
 
586
- _See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/login.ts)_
599
+ _See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/login.ts)_
587
600
 
588
601
  ## `qfg logout`
589
602
 
@@ -606,7 +619,7 @@ EXAMPLES
606
619
  $ qfg logout
607
620
  ```
608
621
 
609
- _See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/logout.ts)_
622
+ _See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/logout.ts)_
610
623
 
611
624
  ## `qfg mcp`
612
625
 
@@ -639,7 +652,7 @@ EXAMPLES
639
652
  $ qfg mcp --url http://local-app.quonfig-staging.com:3003/api/v1/mcp
640
653
  ```
641
654
 
642
- _See code: [src/commands/mcp.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/mcp.ts)_
655
+ _See code: [src/commands/mcp.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/mcp.ts)_
643
656
 
644
657
  ## `qfg migrate`
645
658
 
@@ -693,7 +706,7 @@ EXAMPLES
693
706
  $ qfg migrate --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-config --staging
694
707
  ```
695
708
 
696
- _See code: [src/commands/migrate.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/migrate.ts)_
709
+ _See code: [src/commands/migrate.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/migrate.ts)_
697
710
 
698
711
  ## `qfg migrate doctor`
699
712
 
@@ -731,7 +744,39 @@ EXAMPLES
731
744
  $ qfg migrate doctor --json
732
745
  ```
733
746
 
734
- _See code: [src/commands/migrate/doctor.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/migrate/doctor.ts)_
747
+ _See code: [src/commands/migrate/doctor.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/migrate/doctor.ts)_
748
+
749
+ ## `qfg migrate my-code`
750
+
751
+ Migrate Launch SDK call sites in your codebase to Quonfig SDK call sites (invokes the qfg-migrate-code Claude skill)
752
+
753
+ ```
754
+ USAGE
755
+ $ qfg migrate my-code [--json] [--interactive] [--no-color] [--verbose] [--dry-run] [--from launch]
756
+
757
+ FLAGS
758
+ --dry-run Show what would be migrated without editing any files
759
+ --from=<option> [default: launch] Legacy SDK to migrate from
760
+ <options: launch>
761
+
762
+ GLOBAL FLAGS
763
+ --[no-]interactive Force interactive mode
764
+ --json Format output as json.
765
+ --no-color Do not colorize output
766
+ --verbose Verbose output
767
+
768
+ DESCRIPTION
769
+ Migrate Launch SDK call sites in your codebase to Quonfig SDK call sites (invokes the qfg-migrate-code Claude skill)
770
+
771
+ EXAMPLES
772
+ $ qfg migrate my-code
773
+
774
+ $ qfg migrate my-code --from launch
775
+
776
+ $ qfg migrate my-code --dry-run
777
+ ```
778
+
779
+ _See code: [src/commands/migrate/my-code.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/migrate/my-code.ts)_
735
780
 
736
781
  ## `qfg migrate status`
737
782
 
@@ -762,11 +807,11 @@ EXAMPLES
762
807
  $ qfg migrate status --json
763
808
  ```
764
809
 
765
- _See code: [src/commands/migrate/status.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/migrate/status.ts)_
810
+ _See code: [src/commands/migrate/status.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/migrate/status.ts)_
766
811
 
767
812
  ## `qfg override [NAME]`
768
813
 
769
- Override the value of an item for your user/SDK key combo
814
+ Override the value of an item for your user/SDK key combo.
770
815
 
771
816
  ```
772
817
  USAGE
@@ -789,7 +834,12 @@ GLOBAL FLAGS
789
834
  --verbose Verbose output
790
835
 
791
836
  DESCRIPTION
792
- Override the value of an item for your user/SDK key combo
837
+ Override the value of an item for your user/SDK key combo.
838
+
839
+ To target users other than yourself, or to express rules like "user.email == X → value Y",
840
+ you cannot use override — see:
841
+ qfg config-schema # operator reference + worked multi-rule example
842
+ qfg pull # clone the workspace so you can edit JSON directly
793
843
 
794
844
  EXAMPLES
795
845
  $ qfg override # will prompt for name and value
@@ -801,7 +851,7 @@ EXAMPLES
801
851
  $ qfg override my.double.config --value=3.14159
802
852
  ```
803
853
 
804
- _See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/override.ts)_
854
+ _See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/override.ts)_
805
855
 
806
856
  ## `qfg pull`
807
857
 
@@ -845,7 +895,7 @@ EXAMPLES
845
895
  $ qfg pull # uses QUONFIG_DIR env var
846
896
  ```
847
897
 
848
- _See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/pull.ts)_
898
+ _See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/pull.ts)_
849
899
 
850
900
  ## `qfg schema NAME`
851
901
 
@@ -883,7 +933,7 @@ EXAMPLES
883
933
  $ qfg schema my-schema --set-json-schema=@schemas/my-schema.json --protected
884
934
  ```
885
935
 
886
- _See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/schema.ts)_
936
+ _See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/schema.ts)_
887
937
 
888
938
  ## `qfg sdk-key`
889
939
 
@@ -910,7 +960,7 @@ EXAMPLES
910
960
  $ qfg sdk-key revoke <key-id>
911
961
  ```
912
962
 
913
- _See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/sdk-key.ts)_
963
+ _See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/sdk-key.ts)_
914
964
 
915
965
  ## `qfg sdk-key create`
916
966
 
@@ -942,7 +992,7 @@ EXAMPLES
942
992
  $ qfg sdk-key create --environment staging --type browser
943
993
  ```
944
994
 
945
- _See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/sdk-key/create.ts)_
995
+ _See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/sdk-key/create.ts)_
946
996
 
947
997
  ## `qfg sdk-key list`
948
998
 
@@ -971,7 +1021,7 @@ EXAMPLES
971
1021
  $ qfg sdk-key list --environment production
972
1022
  ```
973
1023
 
974
- _See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/sdk-key/list.ts)_
1024
+ _See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/sdk-key/list.ts)_
975
1025
 
976
1026
  ## `qfg sdk-key revoke KEYID`
977
1027
 
@@ -998,7 +1048,7 @@ EXAMPLES
998
1048
  $ qfg sdk-key revoke a1b2c3d4-e5f6-7890-abcd-ef1234567890
999
1049
  ```
1000
1050
 
1001
- _See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/sdk-key/revoke.ts)_
1051
+ _See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/sdk-key/revoke.ts)_
1002
1052
 
1003
1053
  ## `qfg set-default [NAME]`
1004
1054
 
@@ -1063,9 +1113,13 @@ EXAMPLES
1063
1113
  # For a percentage rollout, use set-rollout instead:
1064
1114
 
1065
1115
  $ qfg set-rollout my.flag.name --environment production --true-percent 20
1116
+
1117
+ # For per-user / per-property targeting (e.g. user.email == X), edit JSON directly:
1118
+
1119
+ $ qfg pull && qfg config-schema
1066
1120
  ```
1067
1121
 
1068
- _See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/set-default.ts)_
1122
+ _See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/set-default.ts)_
1069
1123
 
1070
1124
  ## `qfg set-rollout [NAME]`
1071
1125
 
@@ -1142,7 +1196,7 @@ EXAMPLES
1142
1196
  $ qfg set-rollout my.variant.flag --environment production --weights "a:33,b:33,c:34" --hash-by user.id
1143
1197
  ```
1144
1198
 
1145
- _See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/set-rollout.ts)_
1199
+ _See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/set-rollout.ts)_
1146
1200
 
1147
1201
  ## `qfg sync`
1148
1202
 
@@ -1174,7 +1228,7 @@ EXAMPLES
1174
1228
  $ qfg sync --watch --dir ./our-config --interval 30
1175
1229
  ```
1176
1230
 
1177
- _See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/sync.ts)_
1231
+ _See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/sync.ts)_
1178
1232
 
1179
1233
  ## `qfg toggle [NAME]`
1180
1234
 
@@ -1239,6 +1293,10 @@ EXAMPLES
1239
1293
  # For a percentage rollout, use set-rollout instead:
1240
1294
 
1241
1295
  $ qfg set-rollout my.flag.name --environment production --true-percent 20
1296
+
1297
+ # For per-user / per-property targeting (e.g. user.email == X), edit JSON directly:
1298
+
1299
+ $ qfg pull && qfg config-schema
1242
1300
  ```
1243
1301
 
1244
1302
  ## `qfg verify [PATH]`
@@ -1272,7 +1330,7 @@ EXAMPLES
1272
1330
  $ qfg verify --json
1273
1331
  ```
1274
1332
 
1275
- _See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/verify.ts)_
1333
+ _See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/verify.ts)_
1276
1334
 
1277
1335
  ## `qfg whoami`
1278
1336
 
@@ -1295,7 +1353,7 @@ EXAMPLES
1295
1353
  $ qfg whoami
1296
1354
  ```
1297
1355
 
1298
- _See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/whoami.ts)_
1356
+ _See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/whoami.ts)_
1299
1357
 
1300
1358
  ## `qfg workspace`
1301
1359
 
@@ -1318,7 +1376,7 @@ EXAMPLES
1318
1376
  $ qfg workspace
1319
1377
  ```
1320
1378
 
1321
- _See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/workspace.ts)_
1379
+ _See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/workspace.ts)_
1322
1380
 
1323
1381
  ## `qfg workspace bootstrap`
1324
1382
 
@@ -1351,7 +1409,7 @@ EXAMPLES
1351
1409
  $ qfg workspace bootstrap --dir ./our-config --skip-validate
1352
1410
  ```
1353
1411
 
1354
- _See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/workspace/bootstrap.ts)_
1412
+ _See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/workspace/bootstrap.ts)_
1355
1413
 
1356
1414
  ## `qfg workspace switch`
1357
1415
 
@@ -1374,7 +1432,7 @@ EXAMPLES
1374
1432
  $ qfg workspace switch
1375
1433
  ```
1376
1434
 
1377
- _See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/workspace/switch.ts)_
1435
+ _See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.14/src/commands/workspace/switch.ts)_
1378
1436
  <!-- commandsstop -->
1379
1437
 
1380
1438
  ## Local Development
@@ -100,11 +100,11 @@ function schemaToZod(schema) {
100
100
  const items = schema.prefixItems.map((item) => schemaToZod(item));
101
101
  result = z.tuple(items);
102
102
  }
103
- else if (schema.items !== undefined) {
104
- result = z.array(schemaToZod(schema.items));
103
+ else if (schema.items === undefined) {
104
+ result = z.array(z.any());
105
105
  }
106
106
  else {
107
- result = z.array(z.any());
107
+ result = z.array(schemaToZod(schema.items));
108
108
  }
109
109
  break;
110
110
  }
@@ -121,12 +121,14 @@ function schemaToZod(schema) {
121
121
  default: {
122
122
  if (Array.isArray(schema.oneOf)) {
123
123
  const options = schema.oneOf.map((item) => schemaToZod(item));
124
- result = options.length === 1 ? options[0] : z.union(options);
124
+ result =
125
+ options.length === 1 ? options[0] : z.union(options);
125
126
  break;
126
127
  }
127
128
  if (Array.isArray(schema.anyOf)) {
128
129
  const options = schema.anyOf.map((item) => schemaToZod(item));
129
- result = options.length === 1 ? options[0] : z.union(options);
130
+ result =
131
+ options.length === 1 ? options[0] : z.union(options);
130
132
  break;
131
133
  }
132
134
  if (Array.isArray(schema.allOf) && schema.allOf.length === 1) {
@@ -20,12 +20,12 @@ export declare abstract class ZodBaseMapper {
20
20
  protected abstract function(args: string, returns: string): string;
21
21
  protected abstract functionArguments(value?: $ZodFunctionArgs): string;
22
22
  protected abstract functionReturns(value: $ZodFunctionOut): string;
23
- protected abstract null(): string;
24
23
  protected abstract literal(value: string | number | boolean | null): string;
24
+ protected abstract never(): string;
25
+ protected abstract null(): string;
25
26
  protected abstract number(isInteger: boolean): string;
26
27
  protected abstract object(properties: [string, z.ZodTypeAny][]): string;
27
28
  protected abstract optional(wrappedType: string): string;
28
- protected abstract never(): string;
29
29
  protected abstract record(keyType: string, valueType: string): string;
30
30
  protected abstract string(): string;
31
31
  protected abstract tuple(wrappedTypes: string[]): string;
@@ -9,12 +9,12 @@ export declare class ZodToStringMapper extends ZodBaseMapper {
9
9
  function(input: string, output: string): string;
10
10
  functionArguments(value?: $ZodFunctionArgs): string;
11
11
  functionReturns(value: $ZodFunctionOut): string;
12
- null(): string;
13
12
  literal(value: string | number | boolean | null): string;
13
+ never(): string;
14
+ null(): string;
14
15
  number(isInteger?: boolean): "z.number()" | "z.number().int()";
15
16
  object(properties: [string, z.ZodTypeAny][]): string;
16
17
  optional(wrappedType: string): string;
17
- never(): string;
18
18
  record(keyType: string, valueType: string): string;
19
19
  renderField(type: z.ZodTypeAny, key?: string): string;
20
20
  string(): string;
@@ -31,12 +31,15 @@ export class ZodToStringMapper extends ZodBaseMapper {
31
31
  const mapper = new ZodToStringMapper();
32
32
  return mapper.resolveType(value);
33
33
  }
34
- null() {
35
- return 'z.null()';
36
- }
37
34
  literal(value) {
38
35
  return `z.literal(${JSON.stringify(value)})`;
39
36
  }
37
+ never() {
38
+ return 'z.never()';
39
+ }
40
+ null() {
41
+ return 'z.null()';
42
+ }
40
43
  number(isInteger = false) {
41
44
  const base = 'z.number()';
42
45
  if (isInteger) {
@@ -56,9 +59,6 @@ export class ZodToStringMapper extends ZodBaseMapper {
56
59
  optional(wrappedType) {
57
60
  return `${wrappedType}.optional()`;
58
61
  }
59
- never() {
60
- return 'z.never()';
61
- }
62
62
  record(keyType, valueType) {
63
63
  return `z.record(${keyType}, ${valueType})`;
64
64
  }
@@ -18,12 +18,12 @@ export declare class ZodToTypescriptMapper extends ZodBaseMapper {
18
18
  function(args: string, returns: string): string;
19
19
  functionArguments(value?: z.ZodTuple): string;
20
20
  functionReturns(value: z.ZodTypeAny): string;
21
- null(): string;
22
21
  literal(value: string | number | boolean | null): string;
22
+ never(): string;
23
+ null(): string;
23
24
  number(): string;
24
25
  object(properties: [string, z.ZodTypeAny][]): string;
25
26
  optional(wrappedType: string): string;
26
- never(): string;
27
27
  record(keyType: string, valueType: string): string;
28
28
  renderField(type: ZodTypeSupported): string;
29
29
  string(): string;
@@ -41,12 +41,15 @@ export class ZodToTypescriptMapper extends ZodBaseMapper {
41
41
  const mapper = new ZodToTypescriptMapper();
42
42
  return mapper.resolveType(value);
43
43
  }
44
- null() {
45
- return 'null';
46
- }
47
44
  literal(value) {
48
45
  return JSON.stringify(value);
49
46
  }
47
+ never() {
48
+ return 'never';
49
+ }
50
+ null() {
51
+ return 'null';
52
+ }
50
53
  number() {
51
54
  return 'number';
52
55
  }
@@ -68,9 +71,6 @@ export class ZodToTypescriptMapper extends ZodBaseMapper {
68
71
  // Fallback to a union type w/undefined for inline optional definitions
69
72
  return this.union([wrappedType, 'undefined']);
70
73
  }
71
- never() {
72
- return 'never';
73
- }
74
74
  record(keyType, valueType) {
75
75
  return `Record<${keyType}, ${valueType}>`;
76
76
  }
@@ -17,12 +17,12 @@ export declare class ZodToTypescriptReturnValueMapper extends ZodBaseMapper {
17
17
  function(args: string, returns: string): string;
18
18
  functionArguments(value?: z.ZodTuple): string;
19
19
  functionReturns(): string;
20
- null(): string;
21
20
  literal(): string;
21
+ never(): string;
22
+ null(): string;
22
23
  number(): string;
23
24
  object(properties: [string, z.ZodTypeAny][]): string;
24
25
  optional(wrappedType: string): string;
25
- never(): string;
26
26
  record(): string;
27
27
  renderField(type: ZodTypeSupported): string;
28
28
  string(): string;
@@ -36,10 +36,13 @@ export class ZodToTypescriptReturnValueMapper extends ZodBaseMapper {
36
36
  functionReturns() {
37
37
  return `Mustache.render(raw${this.printPropertyPath()} ?? "", ${this.FUNCTION_ARGUMENTS_NAME})`;
38
38
  }
39
- null() {
39
+ literal() {
40
40
  return `raw${this.printPropertyPath()}`;
41
41
  }
42
- literal() {
42
+ never() {
43
+ return `raw${this.printPropertyPath()}`;
44
+ }
45
+ null() {
43
46
  return `raw${this.printPropertyPath()}`;
44
47
  }
45
48
  number() {
@@ -65,9 +68,6 @@ export class ZodToTypescriptReturnValueMapper extends ZodBaseMapper {
65
68
  // Fallback to a union type w/undefined for inline optional definitions
66
69
  return this.union([wrappedType, 'undefined']);
67
70
  }
68
- never() {
69
- return `raw${this.printPropertyPath()}`;
70
- }
71
71
  record() {
72
72
  // Explicitly not supporting navigation into record values, as the keys are not known at compile time
73
73
  return `raw${this.printPath(this.returnTypePropertyPath)}`;
@@ -18,7 +18,6 @@ function mapGitValue(gitValue) {
18
18
  case 'string_list': {
19
19
  return { value: { string: JSON.stringify(value) } };
20
20
  }
21
- case 'string':
22
21
  default: {
23
22
  return { value: { string: value } };
24
23
  }
@@ -216,8 +216,11 @@ export class SchemaExtractor {
216
216
  return;
217
217
  }
218
218
  const schemaFile = configFile.schemas?.find((schema) => {
219
- const schemaPath = schema.path.replace(/\\/g, '/');
220
- const derivedKey = schemaPath.split('/').at(-1)?.replace(/\.json$/, '');
219
+ const schemaPath = schema.path.replaceAll('\\', '/');
220
+ const derivedKey = schemaPath
221
+ .split('/')
222
+ .at(-1)
223
+ ?.replace(/\.json$/, '');
221
224
  return derivedKey === schemaKey;
222
225
  });
223
226
  if (schemaFile) {
@@ -195,7 +195,6 @@ Related commands:
195
195
  // Fetch stats for all environments (similar to original implementation)
196
196
  const endTime = Date.now();
197
197
  const startTime = endTime - 24 * 60 * 60 * 1000; // 24 hours ago
198
- const timeInterval = 'HOURLY';
199
198
  const statsPerEnv = {};
200
199
  // Fetch stats for each environment via oRPC
201
200
  for (const env of environments) {
@@ -275,6 +274,10 @@ Related commands:
275
274
  if (value.type === 'stringList' && Array.isArray(value.value)) {
276
275
  return value.value.join(',');
277
276
  }
277
+ // JSON values must be stringified, else they render as [object Object]
278
+ if (value.type === 'json') {
279
+ return JSON.stringify(value.value);
280
+ }
278
281
  return String(value.value);
279
282
  }
280
283
  // New format: {string: 'abc'}
@@ -55,7 +55,12 @@ export default class Init extends BaseCommand {
55
55
  this.log(' Nothing to do.');
56
56
  }
57
57
  if (this.jsonEnabled()) {
58
- return { actions: plan.actions, dryRun: true, isFirstTime: plan.isFirstTime, samplesIncluded: plan.samplesIncluded };
58
+ return {
59
+ actions: plan.actions,
60
+ dryRun: true,
61
+ isFirstTime: plan.isFirstTime,
62
+ samplesIncluded: plan.samplesIncluded,
63
+ };
59
64
  }
60
65
  return plan;
61
66
  }
@@ -76,7 +81,12 @@ export default class Init extends BaseCommand {
76
81
  }
77
82
  this.log('\nRun `qfg verify` to validate the workspace.');
78
83
  if (this.jsonEnabled()) {
79
- return { actions: plan.actions, dryRun: false, isFirstTime: plan.isFirstTime, samplesIncluded: plan.samplesIncluded };
84
+ return {
85
+ actions: plan.actions,
86
+ dryRun: false,
87
+ isFirstTime: plan.isFirstTime,
88
+ samplesIncluded: plan.samplesIncluded,
89
+ };
80
90
  }
81
91
  return plan;
82
92
  }
@@ -1,5 +1,6 @@
1
1
  import { BaseCommand } from '../index.js';
2
2
  export default class Interactive extends BaseCommand {
3
+ static description: string;
3
4
  static examples: string[];
4
5
  run(): Promise<void>;
5
6
  }
@@ -1,6 +1,14 @@
1
1
  import { BaseCommand } from '../index.js';
2
2
  import { interactivePrompt } from '../interactive-prompt.js';
3
3
  export default class Interactive extends BaseCommand {
4
+ static description = `Launch an interactive menu to browse and manage your workspace.
5
+
6
+ Common shortcuts:
7
+ qfg set-default my.flag --environment production --value false # catch-all fallback
8
+ qfg set-rollout my.flag --environment production --true-percent 20 # % rollout
9
+
10
+ For arbitrary targeting rules (e.g. user.email, plan, segment, custom property),
11
+ run 'qfg config-schema' then 'qfg pull' and edit the JSON config directly.`;
4
12
  static examples = ['<%= config.bin %>'];
5
13
  async run() {
6
14
  await interactivePrompt(this.config);