@quonfig/cli 0.0.11 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -28
- package/dist/commands/migrate/doctor.d.ts +12 -0
- package/dist/commands/migrate/doctor.js +63 -0
- package/dist/commands/migrate/status.d.ts +10 -0
- package/dist/commands/migrate/status.js +112 -0
- package/dist/commands/migrate.d.ts +20 -0
- package/dist/commands/migrate.js +256 -0
- package/dist/migrate/doctor.d.ts +27 -0
- package/dist/migrate/doctor.js +220 -0
- package/dist/migrate/identifier-map.d.ts +14 -0
- package/dist/migrate/identifier-map.js +55 -0
- package/dist/migrate/import-state.d.ts +14 -0
- package/dist/migrate/import-state.js +60 -0
- package/dist/migrate/migration-report.d.ts +42 -0
- package/dist/migrate/migration-report.js +93 -0
- package/dist/migrate/push-strategy.d.ts +34 -0
- package/dist/migrate/push-strategy.js +133 -0
- package/dist/migrate/push-to-cloud.d.ts +15 -0
- package/dist/migrate/push-to-cloud.js +31 -0
- package/dist/migrate/registry.d.ts +6 -0
- package/dist/migrate/registry.js +25 -0
- package/dist/migrate/source.d.ts +22 -0
- package/dist/migrate/source.js +12 -0
- package/dist/migrate/sources/flagsmith.d.ts +2 -0
- package/dist/migrate/sources/flagsmith.js +18 -0
- package/dist/migrate/sources/launch/api.d.ts +7 -0
- package/dist/migrate/sources/launch/api.js +75 -0
- package/dist/migrate/sources/launch/translate.d.ts +6 -0
- package/dist/migrate/sources/launch/translate.js +190 -0
- package/dist/migrate/sources/launch/types.d.ts +68 -0
- package/dist/migrate/sources/launch/types.js +1 -0
- package/dist/migrate/sources/launch.d.ts +3 -0
- package/dist/migrate/sources/launch.js +70 -0
- package/dist/migrate/sources/launchdarkly.d.ts +2 -0
- package/dist/migrate/sources/launchdarkly.js +18 -0
- package/dist/ui/get-confirmation.d.ts +2 -1
- package/dist/ui/get-confirmation.js +9 -1
- package/dist/ui/get-value.d.ts +1 -1
- package/dist/ui/get-value.js +3 -2
- package/dist/util/is-interactive.d.ts +21 -1
- package/dist/util/is-interactive.js +21 -1
- package/dist/verify/validate.js +6 -1
- package/oclif.manifest.json +287 -1
- package/package.json +1 -1
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.
|
|
17
|
+
@quonfig/cli/0.0.12 linux-x64 node-v24.4.1
|
|
18
18
|
$ qfg --help [COMMAND]
|
|
19
19
|
USAGE
|
|
20
20
|
$ qfg COMMAND
|
|
@@ -40,6 +40,9 @@ USAGE
|
|
|
40
40
|
* [`qfg login`](#qfg-login)
|
|
41
41
|
* [`qfg logout`](#qfg-logout)
|
|
42
42
|
* [`qfg mcp`](#qfg-mcp)
|
|
43
|
+
* [`qfg migrate`](#qfg-migrate)
|
|
44
|
+
* [`qfg migrate doctor`](#qfg-migrate-doctor)
|
|
45
|
+
* [`qfg migrate status`](#qfg-migrate-status)
|
|
43
46
|
* [`qfg override [NAME]`](#qfg-override-name)
|
|
44
47
|
* [`qfg pull`](#qfg-pull)
|
|
45
48
|
* [`qfg schema NAME`](#qfg-schema-name)
|
|
@@ -84,7 +87,7 @@ EXAMPLES
|
|
|
84
87
|
$ qfg config-schema --json-schema # full JSON Schema document (copy into your editor)
|
|
85
88
|
```
|
|
86
89
|
|
|
87
|
-
_See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
90
|
+
_See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/config-schema.ts)_
|
|
88
91
|
|
|
89
92
|
## `qfg create NAME`
|
|
90
93
|
|
|
@@ -156,7 +159,7 @@ EXAMPLES
|
|
|
156
159
|
$ qfg set-rollout my.new.flag --environment production --true-percent 20
|
|
157
160
|
```
|
|
158
161
|
|
|
159
|
-
_See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
162
|
+
_See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/create.ts)_
|
|
160
163
|
|
|
161
164
|
## `qfg flag info [NAME]`
|
|
162
165
|
|
|
@@ -356,7 +359,7 @@ EXAMPLES
|
|
|
356
359
|
$ qfg generate --targets node-ts -o ./dist # combine with targets
|
|
357
360
|
```
|
|
358
361
|
|
|
359
|
-
_See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
362
|
+
_See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/generate.ts)_
|
|
360
363
|
|
|
361
364
|
## `qfg generate-new-hex-key`
|
|
362
365
|
|
|
@@ -379,7 +382,7 @@ EXAMPLES
|
|
|
379
382
|
$ qfg generate-new-hex-key
|
|
380
383
|
```
|
|
381
384
|
|
|
382
|
-
_See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
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)_
|
|
383
386
|
|
|
384
387
|
## `qfg get [NAME]`
|
|
385
388
|
|
|
@@ -411,7 +414,7 @@ EXAMPLES
|
|
|
411
414
|
$ qfg get my.config.name --environment=production
|
|
412
415
|
```
|
|
413
416
|
|
|
414
|
-
_See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
417
|
+
_See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/get.ts)_
|
|
415
418
|
|
|
416
419
|
## `qfg info [NAME]`
|
|
417
420
|
|
|
@@ -459,7 +462,7 @@ EXAMPLES
|
|
|
459
462
|
$ qfg info my.config.name --exclude-evaluations # skip 24h stats
|
|
460
463
|
```
|
|
461
464
|
|
|
462
|
-
_See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
465
|
+
_See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/info.ts)_
|
|
463
466
|
|
|
464
467
|
## `qfg init [DIRECTORY]`
|
|
465
468
|
|
|
@@ -497,7 +500,7 @@ EXAMPLES
|
|
|
497
500
|
$ qfg init --dry-run
|
|
498
501
|
```
|
|
499
502
|
|
|
500
|
-
_See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
503
|
+
_See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/init.ts)_
|
|
501
504
|
|
|
502
505
|
## `qfg interactive`
|
|
503
506
|
|
|
@@ -515,7 +518,7 @@ EXAMPLES
|
|
|
515
518
|
$ qfg
|
|
516
519
|
```
|
|
517
520
|
|
|
518
|
-
_See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
521
|
+
_See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/interactive.ts)_
|
|
519
522
|
|
|
520
523
|
## `qfg list`
|
|
521
524
|
|
|
@@ -555,7 +558,7 @@ EXAMPLES
|
|
|
555
558
|
$ qfg list --feature-flags
|
|
556
559
|
```
|
|
557
560
|
|
|
558
|
-
_See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
561
|
+
_See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/list.ts)_
|
|
559
562
|
|
|
560
563
|
## `qfg login`
|
|
561
564
|
|
|
@@ -580,7 +583,7 @@ EXAMPLES
|
|
|
580
583
|
$ qfg login --profile myprofile
|
|
581
584
|
```
|
|
582
585
|
|
|
583
|
-
_See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
586
|
+
_See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/login.ts)_
|
|
584
587
|
|
|
585
588
|
## `qfg logout`
|
|
586
589
|
|
|
@@ -603,7 +606,7 @@ EXAMPLES
|
|
|
603
606
|
$ qfg logout
|
|
604
607
|
```
|
|
605
608
|
|
|
606
|
-
_See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
609
|
+
_See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/logout.ts)_
|
|
607
610
|
|
|
608
611
|
## `qfg mcp`
|
|
609
612
|
|
|
@@ -636,7 +639,130 @@ EXAMPLES
|
|
|
636
639
|
$ qfg mcp --url http://local-app.quonfig-staging.com:3003/api/v1/mcp
|
|
637
640
|
```
|
|
638
641
|
|
|
639
|
-
_See code: [src/commands/mcp.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
642
|
+
_See code: [src/commands/mcp.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/mcp.ts)_
|
|
643
|
+
|
|
644
|
+
## `qfg migrate`
|
|
645
|
+
|
|
646
|
+
Migrate flags and configs from a legacy feature-flag system into a Quonfig workspace.
|
|
647
|
+
|
|
648
|
+
```
|
|
649
|
+
USAGE
|
|
650
|
+
$ qfg migrate --from launch|launchdarkly|flagsmith [--json] [--interactive] [--no-color] [--verbose]
|
|
651
|
+
[--api-key <value>] [--dir <value>] [--dry-run] [--push] [--recent <value>] [--reset] [--since <value>] [--staging]
|
|
652
|
+
[--workspace <value>]
|
|
653
|
+
|
|
654
|
+
FLAGS
|
|
655
|
+
--api-key=<value> API key for the legacy source (or set LAUNCH_API_KEY)
|
|
656
|
+
--dir=<value> Target local workspace directory. Defaults to cwd if it looks like a Quonfig workspace, otherwise
|
|
657
|
+
./quonfig-config.
|
|
658
|
+
--dry-run Fetch and summarize changes without writing anything
|
|
659
|
+
--from=<option> (required) Legacy source to migrate from
|
|
660
|
+
<options: launch|launchdarkly|flagsmith>
|
|
661
|
+
--push After migrating to a local dir, also push to the given --workspace on Quonfig cloud
|
|
662
|
+
--recent=<value> Import only the last N changes (useful for tire-kicking)
|
|
663
|
+
--reset Ignore the delta cursor and re-import everything from scratch
|
|
664
|
+
--since=<value> Override the delta cursor (epoch milliseconds or ISO-8601 timestamp)
|
|
665
|
+
--staging Hit the staging API for the source (dev-only)
|
|
666
|
+
--workspace=<value> Quonfig cloud workspace slug to push to. Requires `qfg login` and is typically combined with
|
|
667
|
+
--push.
|
|
668
|
+
|
|
669
|
+
GLOBAL FLAGS
|
|
670
|
+
--[no-]interactive Force interactive mode
|
|
671
|
+
--json Format output as json.
|
|
672
|
+
--no-color Do not colorize output
|
|
673
|
+
--verbose Verbose output
|
|
674
|
+
|
|
675
|
+
DESCRIPTION
|
|
676
|
+
Migrate flags and configs from a legacy feature-flag system into a Quonfig workspace.
|
|
677
|
+
|
|
678
|
+
Currently supported sources:
|
|
679
|
+
launch — Reforge Launch (ported from launch-migrator)
|
|
680
|
+
|
|
681
|
+
See https://docs.quonfig.com/docs/migrating/from-launch for the step-by-step guide,
|
|
682
|
+
and https://docs.quonfig.com/docs/migrating/troubleshooting when something goes sideways.
|
|
683
|
+
|
|
684
|
+
EXAMPLES
|
|
685
|
+
$ qfg migrate --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-config
|
|
686
|
+
|
|
687
|
+
$ qfg migrate --from launch --api-key $LAUNCH_API_KEY --workspace acme-prod --push
|
|
688
|
+
|
|
689
|
+
$ qfg migrate --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-config --reset
|
|
690
|
+
|
|
691
|
+
$ qfg migrate --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-config --dry-run
|
|
692
|
+
|
|
693
|
+
$ qfg migrate --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-config --staging
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
_See code: [src/commands/migrate.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/migrate.ts)_
|
|
697
|
+
|
|
698
|
+
## `qfg migrate doctor`
|
|
699
|
+
|
|
700
|
+
Preflight health checks for `qfg migrate`. Verifies auth, workspace provisioning, working tree, and identifier collisions.
|
|
701
|
+
|
|
702
|
+
```
|
|
703
|
+
USAGE
|
|
704
|
+
$ qfg migrate doctor [--json] [--interactive] [--no-color] [--verbose] [--api-key <value>] [--dir <value>] [--from
|
|
705
|
+
launch] [--language <value>]
|
|
706
|
+
|
|
707
|
+
FLAGS
|
|
708
|
+
--api-key=<value> Legacy SDK API key to validate against the source
|
|
709
|
+
--dir=<value> [default: .] Workspace directory to check (git clean / identifier map)
|
|
710
|
+
--from=<option> [default: launch] Legacy SDK to migrate from
|
|
711
|
+
<options: launch>
|
|
712
|
+
--language=<value> Customer SDK language — used to warn when datadir mode is unavailable (e.g. javascript-browser)
|
|
713
|
+
|
|
714
|
+
GLOBAL FLAGS
|
|
715
|
+
--[no-]interactive Force interactive mode
|
|
716
|
+
--json Format output as json.
|
|
717
|
+
--no-color Do not colorize output
|
|
718
|
+
--verbose Verbose output
|
|
719
|
+
|
|
720
|
+
DESCRIPTION
|
|
721
|
+
Preflight health checks for `qfg migrate`. Verifies auth, workspace provisioning, working tree, and identifier
|
|
722
|
+
collisions.
|
|
723
|
+
|
|
724
|
+
EXAMPLES
|
|
725
|
+
$ qfg migrate doctor
|
|
726
|
+
|
|
727
|
+
$ qfg migrate doctor --from launch --api-key $LAUNCH_API_KEY
|
|
728
|
+
|
|
729
|
+
$ qfg migrate doctor --dir ./my-workspace --language node
|
|
730
|
+
|
|
731
|
+
$ qfg migrate doctor --json
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
_See code: [src/commands/migrate/doctor.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/migrate/doctor.ts)_
|
|
735
|
+
|
|
736
|
+
## `qfg migrate status`
|
|
737
|
+
|
|
738
|
+
Show the status of a workspace migrated with `qfg migrate`. Reads .qf/import-state.json and summarizes source, counts, and next steps.
|
|
739
|
+
|
|
740
|
+
```
|
|
741
|
+
USAGE
|
|
742
|
+
$ qfg migrate status [--json] [--interactive] [--no-color] [--verbose] [--dir <value>]
|
|
743
|
+
|
|
744
|
+
FLAGS
|
|
745
|
+
--dir=<value> [default: .] Workspace directory to inspect
|
|
746
|
+
|
|
747
|
+
GLOBAL FLAGS
|
|
748
|
+
--[no-]interactive Force interactive mode
|
|
749
|
+
--json Format output as json.
|
|
750
|
+
--no-color Do not colorize output
|
|
751
|
+
--verbose Verbose output
|
|
752
|
+
|
|
753
|
+
DESCRIPTION
|
|
754
|
+
Show the status of a workspace migrated with `qfg migrate`. Reads .qf/import-state.json and summarizes source, counts,
|
|
755
|
+
and next steps.
|
|
756
|
+
|
|
757
|
+
EXAMPLES
|
|
758
|
+
$ qfg migrate status
|
|
759
|
+
|
|
760
|
+
$ qfg migrate status --dir ./my-workspace
|
|
761
|
+
|
|
762
|
+
$ qfg migrate status --json
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
_See code: [src/commands/migrate/status.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/migrate/status.ts)_
|
|
640
766
|
|
|
641
767
|
## `qfg override [NAME]`
|
|
642
768
|
|
|
@@ -675,7 +801,7 @@ EXAMPLES
|
|
|
675
801
|
$ qfg override my.double.config --value=3.14159
|
|
676
802
|
```
|
|
677
803
|
|
|
678
|
-
_See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
804
|
+
_See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/override.ts)_
|
|
679
805
|
|
|
680
806
|
## `qfg pull`
|
|
681
807
|
|
|
@@ -719,7 +845,7 @@ EXAMPLES
|
|
|
719
845
|
$ qfg pull # uses QUONFIG_DIR env var
|
|
720
846
|
```
|
|
721
847
|
|
|
722
|
-
_See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
848
|
+
_See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/pull.ts)_
|
|
723
849
|
|
|
724
850
|
## `qfg schema NAME`
|
|
725
851
|
|
|
@@ -757,7 +883,7 @@ EXAMPLES
|
|
|
757
883
|
$ qfg schema my-schema --set-json-schema=@schemas/my-schema.json --protected
|
|
758
884
|
```
|
|
759
885
|
|
|
760
|
-
_See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
886
|
+
_See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/schema.ts)_
|
|
761
887
|
|
|
762
888
|
## `qfg sdk-key`
|
|
763
889
|
|
|
@@ -784,7 +910,7 @@ EXAMPLES
|
|
|
784
910
|
$ qfg sdk-key revoke <key-id>
|
|
785
911
|
```
|
|
786
912
|
|
|
787
|
-
_See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
913
|
+
_See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/sdk-key.ts)_
|
|
788
914
|
|
|
789
915
|
## `qfg sdk-key create`
|
|
790
916
|
|
|
@@ -816,7 +942,7 @@ EXAMPLES
|
|
|
816
942
|
$ qfg sdk-key create --environment staging --type browser
|
|
817
943
|
```
|
|
818
944
|
|
|
819
|
-
_See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
945
|
+
_See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/sdk-key/create.ts)_
|
|
820
946
|
|
|
821
947
|
## `qfg sdk-key list`
|
|
822
948
|
|
|
@@ -845,7 +971,7 @@ EXAMPLES
|
|
|
845
971
|
$ qfg sdk-key list --environment production
|
|
846
972
|
```
|
|
847
973
|
|
|
848
|
-
_See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
974
|
+
_See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/sdk-key/list.ts)_
|
|
849
975
|
|
|
850
976
|
## `qfg sdk-key revoke KEYID`
|
|
851
977
|
|
|
@@ -872,7 +998,7 @@ EXAMPLES
|
|
|
872
998
|
$ qfg sdk-key revoke a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
|
873
999
|
```
|
|
874
1000
|
|
|
875
|
-
_See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1001
|
+
_See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/sdk-key/revoke.ts)_
|
|
876
1002
|
|
|
877
1003
|
## `qfg set-default [NAME]`
|
|
878
1004
|
|
|
@@ -939,7 +1065,7 @@ EXAMPLES
|
|
|
939
1065
|
$ qfg set-rollout my.flag.name --environment production --true-percent 20
|
|
940
1066
|
```
|
|
941
1067
|
|
|
942
|
-
_See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1068
|
+
_See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/set-default.ts)_
|
|
943
1069
|
|
|
944
1070
|
## `qfg set-rollout [NAME]`
|
|
945
1071
|
|
|
@@ -1016,7 +1142,7 @@ EXAMPLES
|
|
|
1016
1142
|
$ qfg set-rollout my.variant.flag --environment production --weights "a:33,b:33,c:34" --hash-by user.id
|
|
1017
1143
|
```
|
|
1018
1144
|
|
|
1019
|
-
_See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1145
|
+
_See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/set-rollout.ts)_
|
|
1020
1146
|
|
|
1021
1147
|
## `qfg sync`
|
|
1022
1148
|
|
|
@@ -1048,7 +1174,7 @@ EXAMPLES
|
|
|
1048
1174
|
$ qfg sync --watch --dir ./our-config --interval 30
|
|
1049
1175
|
```
|
|
1050
1176
|
|
|
1051
|
-
_See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1177
|
+
_See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/sync.ts)_
|
|
1052
1178
|
|
|
1053
1179
|
## `qfg toggle [NAME]`
|
|
1054
1180
|
|
|
@@ -1146,7 +1272,7 @@ EXAMPLES
|
|
|
1146
1272
|
$ qfg verify --json
|
|
1147
1273
|
```
|
|
1148
1274
|
|
|
1149
|
-
_See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1275
|
+
_See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/verify.ts)_
|
|
1150
1276
|
|
|
1151
1277
|
## `qfg whoami`
|
|
1152
1278
|
|
|
@@ -1169,7 +1295,7 @@ EXAMPLES
|
|
|
1169
1295
|
$ qfg whoami
|
|
1170
1296
|
```
|
|
1171
1297
|
|
|
1172
|
-
_See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1298
|
+
_See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/whoami.ts)_
|
|
1173
1299
|
|
|
1174
1300
|
## `qfg workspace`
|
|
1175
1301
|
|
|
@@ -1192,7 +1318,7 @@ EXAMPLES
|
|
|
1192
1318
|
$ qfg workspace
|
|
1193
1319
|
```
|
|
1194
1320
|
|
|
1195
|
-
_See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1321
|
+
_See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/workspace.ts)_
|
|
1196
1322
|
|
|
1197
1323
|
## `qfg workspace bootstrap`
|
|
1198
1324
|
|
|
@@ -1225,7 +1351,7 @@ EXAMPLES
|
|
|
1225
1351
|
$ qfg workspace bootstrap --dir ./our-config --skip-validate
|
|
1226
1352
|
```
|
|
1227
1353
|
|
|
1228
|
-
_See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1354
|
+
_See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/workspace/bootstrap.ts)_
|
|
1229
1355
|
|
|
1230
1356
|
## `qfg workspace switch`
|
|
1231
1357
|
|
|
@@ -1248,7 +1374,7 @@ EXAMPLES
|
|
|
1248
1374
|
$ qfg workspace switch
|
|
1249
1375
|
```
|
|
1250
1376
|
|
|
1251
|
-
_See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1377
|
+
_See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.12/src/commands/workspace/switch.ts)_
|
|
1252
1378
|
<!-- commandsstop -->
|
|
1253
1379
|
|
|
1254
1380
|
## Local Development
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from '../../index.js';
|
|
2
|
+
export default class MigrateDoctor extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
'api-key': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
7
|
+
dir: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
8
|
+
from: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
9
|
+
language: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../index.js';
|
|
3
|
+
import { formatHumanReport, runDoctor, } from '../../migrate/doctor.js';
|
|
4
|
+
import { loadTokens } from '../../util/token-storage.js';
|
|
5
|
+
const SUPPORTED_SOURCES = new Set(['launch']);
|
|
6
|
+
const defaultLoadSession = async () => {
|
|
7
|
+
const tokens = await loadTokens();
|
|
8
|
+
if (!tokens?.accessToken)
|
|
9
|
+
return null;
|
|
10
|
+
return { expiresAt: tokens.expiresAt ?? 0 };
|
|
11
|
+
};
|
|
12
|
+
export default class MigrateDoctor extends BaseCommand {
|
|
13
|
+
static description = 'Preflight health checks for `qfg migrate`. Verifies auth, workspace provisioning, working tree, and identifier collisions.';
|
|
14
|
+
static examples = [
|
|
15
|
+
'<%= config.bin %> <%= command.id %>',
|
|
16
|
+
'<%= config.bin %> <%= command.id %> --from launch --api-key $LAUNCH_API_KEY',
|
|
17
|
+
'<%= config.bin %> <%= command.id %> --dir ./my-workspace --language node',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> --json',
|
|
19
|
+
];
|
|
20
|
+
static flags = {
|
|
21
|
+
'api-key': Flags.string({
|
|
22
|
+
description: 'Legacy SDK API key to validate against the source',
|
|
23
|
+
required: false,
|
|
24
|
+
}),
|
|
25
|
+
dir: Flags.string({
|
|
26
|
+
default: '.',
|
|
27
|
+
description: 'Workspace directory to check (git clean / identifier map)',
|
|
28
|
+
}),
|
|
29
|
+
from: Flags.string({
|
|
30
|
+
default: 'launch',
|
|
31
|
+
description: 'Legacy SDK to migrate from',
|
|
32
|
+
options: ['launch'],
|
|
33
|
+
}),
|
|
34
|
+
language: Flags.string({
|
|
35
|
+
description: 'Customer SDK language — used to warn when datadir mode is unavailable (e.g. javascript-browser)',
|
|
36
|
+
required: false,
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
async run() {
|
|
40
|
+
const { flags } = await this.parse(MigrateDoctor);
|
|
41
|
+
if (!SUPPORTED_SOURCES.has(flags.from)) {
|
|
42
|
+
this.err(`Unsupported --from source: ${flags.from}. Only 'launch' is supported today.`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const ctx = {
|
|
46
|
+
apiKey: flags['api-key'],
|
|
47
|
+
dir: flags.dir,
|
|
48
|
+
from: flags.from,
|
|
49
|
+
language: flags.language,
|
|
50
|
+
loadSession: defaultLoadSession,
|
|
51
|
+
};
|
|
52
|
+
const report = await runDoctor(ctx);
|
|
53
|
+
if (this.jsonEnabled()) {
|
|
54
|
+
process.stdout.write(JSON.stringify(report) + '\n');
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.log(formatHumanReport(report));
|
|
58
|
+
}
|
|
59
|
+
if (!report.passed) {
|
|
60
|
+
this.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { JsonObj } from '../../result.js';
|
|
2
|
+
import { BaseCommand } from '../../index.js';
|
|
3
|
+
export default class MigrateStatus extends BaseCommand {
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
dir: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<JsonObj | void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { BaseCommand } from '../../index.js';
|
|
5
|
+
import { readImportState } from '../../migrate/import-state.js';
|
|
6
|
+
const FLAGS_DIR = 'feature-flags';
|
|
7
|
+
const SEGMENTS_DIR = 'segments';
|
|
8
|
+
const WORKSPACE_FILE = 'quonfig.json';
|
|
9
|
+
const NO_STATE_MESSAGE = 'No migration state found. Run qfg migrate --from <source> first.';
|
|
10
|
+
function countJsonFiles(dir) {
|
|
11
|
+
if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory())
|
|
12
|
+
return 0;
|
|
13
|
+
return fs
|
|
14
|
+
.readdirSync(dir)
|
|
15
|
+
.filter((name) => name.endsWith('.json') && !name.startsWith('.'))
|
|
16
|
+
.length;
|
|
17
|
+
}
|
|
18
|
+
function countEnvironments(dir) {
|
|
19
|
+
const file = path.join(dir, WORKSPACE_FILE);
|
|
20
|
+
if (!fs.existsSync(file))
|
|
21
|
+
return 0;
|
|
22
|
+
try {
|
|
23
|
+
const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
24
|
+
return Array.isArray(parsed.environments) ? parsed.environments.length : 0;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function workspaceCounts(dir) {
|
|
31
|
+
return {
|
|
32
|
+
environments: countEnvironments(dir),
|
|
33
|
+
flags: countJsonFiles(path.join(dir, FLAGS_DIR)),
|
|
34
|
+
segments: countJsonFiles(path.join(dir, SEGMENTS_DIR)),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function toIsoTimestamp(value) {
|
|
38
|
+
if (value == null)
|
|
39
|
+
return null;
|
|
40
|
+
const date = typeof value === 'number' ? new Date(value) : new Date(value);
|
|
41
|
+
if (Number.isNaN(date.getTime()))
|
|
42
|
+
return null;
|
|
43
|
+
return date.toISOString();
|
|
44
|
+
}
|
|
45
|
+
function nextHint(source, counts) {
|
|
46
|
+
if (counts.flags === 0 && counts.segments === 0) {
|
|
47
|
+
return `Run \`qfg migrate --from ${source}\` to import flags and segments.`;
|
|
48
|
+
}
|
|
49
|
+
return `Run \`qfg migrate my-code --from ${source}\` to update your SDK call sites, or re-run \`qfg migrate --from ${source}\` to pick up changes.`;
|
|
50
|
+
}
|
|
51
|
+
function formatHuman(payload) {
|
|
52
|
+
const lines = [];
|
|
53
|
+
lines.push(`Source: ${payload.source}`);
|
|
54
|
+
lines.push(`Source workspace: ${payload.sourceWorkspaceId ?? '(not recorded)'}`);
|
|
55
|
+
lines.push(`Last processed at: ${payload.lastProcessedAtIso ?? '(not recorded)'}`);
|
|
56
|
+
lines.push(`Workspace dir: ${payload.dir}`);
|
|
57
|
+
lines.push('');
|
|
58
|
+
lines.push('Counts:');
|
|
59
|
+
lines.push(` Flags: ${payload.counts.flags}`);
|
|
60
|
+
lines.push(` Segments: ${payload.counts.segments}`);
|
|
61
|
+
lines.push(` Environments: ${payload.counts.environments}`);
|
|
62
|
+
lines.push('');
|
|
63
|
+
lines.push(`Next: ${payload.next}`);
|
|
64
|
+
return lines.join('\n');
|
|
65
|
+
}
|
|
66
|
+
export default class MigrateStatus extends BaseCommand {
|
|
67
|
+
static description = 'Show the status of a workspace migrated with `qfg migrate`. Reads .qf/import-state.json and summarizes source, counts, and next steps.';
|
|
68
|
+
static examples = [
|
|
69
|
+
'<%= config.bin %> <%= command.id %>',
|
|
70
|
+
'<%= config.bin %> <%= command.id %> --dir ./my-workspace',
|
|
71
|
+
'<%= config.bin %> <%= command.id %> --json',
|
|
72
|
+
];
|
|
73
|
+
static flags = {
|
|
74
|
+
dir: Flags.string({
|
|
75
|
+
default: '.',
|
|
76
|
+
description: 'Workspace directory to inspect',
|
|
77
|
+
}),
|
|
78
|
+
};
|
|
79
|
+
async run() {
|
|
80
|
+
const { flags } = await this.parse(MigrateStatus);
|
|
81
|
+
const dir = path.resolve(flags.dir);
|
|
82
|
+
const state = readImportState(dir);
|
|
83
|
+
if (!state) {
|
|
84
|
+
const payload = {
|
|
85
|
+
dir,
|
|
86
|
+
found: false,
|
|
87
|
+
message: NO_STATE_MESSAGE,
|
|
88
|
+
};
|
|
89
|
+
if (this.jsonEnabled())
|
|
90
|
+
return payload;
|
|
91
|
+
this.log(NO_STATE_MESSAGE);
|
|
92
|
+
return payload;
|
|
93
|
+
}
|
|
94
|
+
const counts = workspaceCounts(dir);
|
|
95
|
+
const lastProcessedAtIso = toIsoTimestamp(state.lastProcessedAt);
|
|
96
|
+
const next = nextHint(state.source, counts);
|
|
97
|
+
const payload = {
|
|
98
|
+
counts,
|
|
99
|
+
dir,
|
|
100
|
+
found: true,
|
|
101
|
+
lastProcessedAt: state.lastProcessedAt ?? null,
|
|
102
|
+
lastProcessedAtIso,
|
|
103
|
+
next,
|
|
104
|
+
source: state.source,
|
|
105
|
+
sourceWorkspaceId: state.sourceWorkspaceId ?? null,
|
|
106
|
+
};
|
|
107
|
+
if (this.jsonEnabled())
|
|
108
|
+
return payload;
|
|
109
|
+
this.log(formatHuman(payload));
|
|
110
|
+
return payload;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { JsonObj } from '../result.js';
|
|
2
|
+
import { BaseCommand } from '../index.js';
|
|
3
|
+
export default class Migrate extends BaseCommand {
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
'api-key': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
8
|
+
dir: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
9
|
+
'dry-run': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
10
|
+
from: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
11
|
+
push: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
12
|
+
recent: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
13
|
+
reset: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
14
|
+
since: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
15
|
+
staging: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
16
|
+
workspace: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
17
|
+
};
|
|
18
|
+
run(): Promise<JsonObj | void>;
|
|
19
|
+
private resolvePushWorkspace;
|
|
20
|
+
}
|