@quonfig/cli 0.0.46 → 0.0.48

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 (32) hide show
  1. package/README.md +71 -66
  2. package/dist/commands/migrate.d.ts +2 -0
  3. package/dist/commands/migrate.js +68 -8
  4. package/dist/migrate/local-write.js +4 -0
  5. package/dist/migrate/migration-report.d.ts +9 -0
  6. package/dist/migrate/migration-report.js +68 -0
  7. package/dist/migrate/push-to-cloud.js +2 -0
  8. package/dist/migrate/quonfig-target/operators.d.ts +27 -0
  9. package/dist/migrate/quonfig-target/operators.js +71 -0
  10. package/dist/migrate/quonfig-target/report.d.ts +59 -0
  11. package/dist/migrate/quonfig-target/report.js +39 -0
  12. package/dist/migrate/quonfig-target/ruleset.d.ts +127 -0
  13. package/dist/migrate/quonfig-target/ruleset.js +192 -0
  14. package/dist/migrate/quonfig-target/values.d.ts +38 -0
  15. package/dist/migrate/quonfig-target/values.js +77 -0
  16. package/dist/migrate/source-api-key.d.ts +33 -0
  17. package/dist/migrate/source-api-key.js +43 -0
  18. package/dist/migrate/source.d.ts +10 -0
  19. package/dist/migrate/sources/launchdarkly/api.d.ts +59 -0
  20. package/dist/migrate/sources/launchdarkly/api.js +195 -0
  21. package/dist/migrate/sources/launchdarkly/audit.d.ts +161 -0
  22. package/dist/migrate/sources/launchdarkly/audit.js +172 -0
  23. package/dist/migrate/sources/launchdarkly/translate.d.ts +39 -0
  24. package/dist/migrate/sources/launchdarkly/translate.js +209 -0
  25. package/dist/migrate/sources/launchdarkly/types.d.ts +187 -0
  26. package/dist/migrate/sources/launchdarkly/types.js +10 -0
  27. package/dist/migrate/sources/launchdarkly.d.ts +35 -0
  28. package/dist/migrate/sources/launchdarkly.js +295 -13
  29. package/dist/version.d.ts +1 -1
  30. package/dist/version.js +1 -1
  31. package/oclif.manifest.json +178 -161
  32. package/package.json +5 -5
package/README.md CHANGED
@@ -17,7 +17,7 @@ $ npm install -g @quonfig/cli
17
17
  $ qfg COMMAND
18
18
  running command...
19
19
  $ qfg (--version)
20
- @quonfig/cli/0.0.46 linux-x64 node-v24.4.1
20
+ @quonfig/cli/0.0.48 linux-x64 node-v24.4.1
21
21
  $ qfg --help [COMMAND]
22
22
  USAGE
23
23
  $ qfg COMMAND
@@ -195,7 +195,7 @@ EXAMPLES
195
195
  $ qfg activity restore my.flag --yes
196
196
  ```
197
197
 
198
- _See code: [src/commands/activity.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/activity.ts)_
198
+ _See code: [src/commands/activity.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/activity.ts)_
199
199
 
200
200
  ## `qfg activity deleted`
201
201
 
@@ -224,7 +224,7 @@ EXAMPLES
224
224
  $ qfg activity deleted --json
225
225
  ```
226
226
 
227
- _See code: [src/commands/activity/deleted.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/activity/deleted.ts)_
227
+ _See code: [src/commands/activity/deleted.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/activity/deleted.ts)_
228
228
 
229
229
  ## `qfg activity feed`
230
230
 
@@ -259,7 +259,7 @@ EXAMPLES
259
259
  $ qfg activity feed --json
260
260
  ```
261
261
 
262
- _See code: [src/commands/activity/feed.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/activity/feed.ts)_
262
+ _See code: [src/commands/activity/feed.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/activity/feed.ts)_
263
263
 
264
264
  ## `qfg activity history [NAME]`
265
265
 
@@ -293,7 +293,7 @@ EXAMPLES
293
293
  $ qfg activity history request.timeout --json
294
294
  ```
295
295
 
296
- _See code: [src/commands/activity/history.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/activity/history.ts)_
296
+ _See code: [src/commands/activity/history.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/activity/history.ts)_
297
297
 
298
298
  ## `qfg activity restore [NAME]`
299
299
 
@@ -332,7 +332,7 @@ EXAMPLES
332
332
  $ qfg activity restore request.timeout --type config --yes
333
333
  ```
334
334
 
335
- _See code: [src/commands/activity/restore.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/activity/restore.ts)_
335
+ _See code: [src/commands/activity/restore.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/activity/restore.ts)_
336
336
 
337
337
  ## `qfg audit-log [NAME]`
338
338
 
@@ -360,7 +360,7 @@ EXAMPLES
360
360
  $ qfg audit-log my.flag
361
361
  ```
362
362
 
363
- _See code: [src/commands/audit-log.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/audit-log.ts)_
363
+ _See code: [src/commands/audit-log.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/audit-log.ts)_
364
364
 
365
365
  ## `qfg config-schema`
366
366
 
@@ -389,7 +389,7 @@ EXAMPLES
389
389
  $ qfg config-schema --json-schema # full JSON Schema document (copy into your editor)
390
390
  ```
391
391
 
392
- _See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/config-schema.ts)_
392
+ _See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/config-schema.ts)_
393
393
 
394
394
  ## `qfg create NAME`
395
395
 
@@ -474,7 +474,7 @@ EXAMPLES
474
474
  $ qfg set-rollout my.new.flag --environment production --true-percent 20
475
475
  ```
476
476
 
477
- _See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/create.ts)_
477
+ _See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/create.ts)_
478
478
 
479
479
  ## `qfg delete NAME`
480
480
 
@@ -520,7 +520,7 @@ EXAMPLES
520
520
  $ qfg delete my.config --yes
521
521
  ```
522
522
 
523
- _See code: [src/commands/delete.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/delete.ts)_
523
+ _See code: [src/commands/delete.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/delete.ts)_
524
524
 
525
525
  ## `qfg flag info [NAME]`
526
526
 
@@ -723,7 +723,7 @@ EXAMPLES
723
723
  $ qfg generate --targets node-ts -o ./dist # combine with targets
724
724
  ```
725
725
 
726
- _See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/generate.ts)_
726
+ _See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/generate.ts)_
727
727
 
728
728
  ## `qfg generate-new-hex-key`
729
729
 
@@ -746,7 +746,7 @@ EXAMPLES
746
746
  $ qfg generate-new-hex-key
747
747
  ```
748
748
 
749
- _See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/generate-new-hex-key.ts)_
749
+ _See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/generate-new-hex-key.ts)_
750
750
 
751
751
  ## `qfg get [NAME]`
752
752
 
@@ -778,7 +778,7 @@ EXAMPLES
778
778
  $ qfg get my.config.name --environment=production
779
779
  ```
780
780
 
781
- _See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/get.ts)_
781
+ _See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/get.ts)_
782
782
 
783
783
  ## `qfg history NAME`
784
784
 
@@ -804,7 +804,7 @@ EXAMPLES
804
804
  $ qfg history my.flag
805
805
  ```
806
806
 
807
- _See code: [src/commands/history.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/history.ts)_
807
+ _See code: [src/commands/history.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/history.ts)_
808
808
 
809
809
  ## `qfg info [NAME]`
810
810
 
@@ -852,7 +852,7 @@ EXAMPLES
852
852
  $ qfg info my.config.name --exclude-evaluations # skip 24h stats
853
853
  ```
854
854
 
855
- _See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/info.ts)_
855
+ _See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/info.ts)_
856
856
 
857
857
  ## `qfg init [DIRECTORY]`
858
858
 
@@ -892,7 +892,7 @@ EXAMPLES
892
892
  $ qfg init --dry-run
893
893
  ```
894
894
 
895
- _See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/init.ts)_
895
+ _See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/init.ts)_
896
896
 
897
897
  ## `qfg interactive`
898
898
 
@@ -922,7 +922,7 @@ EXAMPLES
922
922
  $ qfg
923
923
  ```
924
924
 
925
- _See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/interactive.ts)_
925
+ _See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/interactive.ts)_
926
926
 
927
927
  ## `qfg list`
928
928
 
@@ -962,7 +962,7 @@ EXAMPLES
962
962
  $ qfg list --feature-flags
963
963
  ```
964
964
 
965
- _See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/list.ts)_
965
+ _See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/list.ts)_
966
966
 
967
967
  ## `qfg log`
968
968
 
@@ -987,7 +987,7 @@ EXAMPLES
987
987
  $ qfg log --limit 5
988
988
  ```
989
989
 
990
- _See code: [src/commands/log.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/log.ts)_
990
+ _See code: [src/commands/log.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/log.ts)_
991
991
 
992
992
  ## `qfg log-level NAME`
993
993
 
@@ -1052,7 +1052,7 @@ EXAMPLES
1052
1052
  $ qfg log-level log-level.my-app --target=Chatty --value=INFO --environment=production
1053
1053
  ```
1054
1054
 
1055
- _See code: [src/commands/log-level.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/log-level.ts)_
1055
+ _See code: [src/commands/log-level.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/log-level.ts)_
1056
1056
 
1057
1057
  ## `qfg login`
1058
1058
 
@@ -1077,7 +1077,7 @@ EXAMPLES
1077
1077
  $ qfg login --profile myprofile
1078
1078
  ```
1079
1079
 
1080
- _See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/login.ts)_
1080
+ _See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/login.ts)_
1081
1081
 
1082
1082
  ## `qfg logout`
1083
1083
 
@@ -1100,7 +1100,7 @@ EXAMPLES
1100
1100
  $ qfg logout
1101
1101
  ```
1102
1102
 
1103
- _See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/logout.ts)_
1103
+ _See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/logout.ts)_
1104
1104
 
1105
1105
  ## `qfg migrate`
1106
1106
 
@@ -1109,26 +1109,31 @@ Migrate flags and configs from a legacy feature-flag system into a Quonfig works
1109
1109
  ```
1110
1110
  USAGE
1111
1111
  $ qfg migrate --from launch|launchdarkly|flagsmith [--json] [--interactive] [--no-color] [--verbose]
1112
- [--api-key <value>] [--dir <value>] [--dry-run] [--full-summary] [--push] [--recent <value>] [--reset] [--since
1113
- <value>] [--staging] [--workspace <value>]
1112
+ [--api-key <value>] [--dir <value>] [--dry-run] [--full-summary] [--project <value>] [--push] [--recent <value>]
1113
+ [--reset] [--since <value>] [--source-api-key <value>] [--staging] [--workspace <value>]
1114
1114
 
1115
1115
  FLAGS
1116
- --api-key=<value> API key for the legacy source (or set LAUNCH_API_KEY)
1117
- --dir=<value> Target local workspace directory. Defaults to cwd if it looks like a Quonfig workspace, otherwise
1118
- ./quonfig-repo.
1119
- --dry-run Fetch and summarize changes without writing anything
1120
- --from=<option> (required) Legacy source to migrate from
1121
- <options: launch|launchdarkly|flagsmith>
1122
- --full-summary Reify the full source-side audit log into per-change git commits (author = original user, date =
1123
- original timestamp, message = change summary). Only valid on first-run imports — pass --reset to
1124
- re-import everything from scratch with this flag.
1125
- --push After migrating to a local dir, also push to the given --workspace on Quonfig cloud
1126
- --recent=<value> Import only the last N changes (useful for tire-kicking)
1127
- --reset Ignore the delta cursor and re-import everything from scratch
1128
- --since=<value> Override the delta cursor (epoch milliseconds or ISO-8601 timestamp)
1129
- --staging Hit the staging API for the source (dev-only)
1130
- --workspace=<value> Quonfig cloud workspace slug to push to. Requires `qfg login` and is typically combined with
1131
- --push.
1116
+ --api-key=<value> Deprecated alias for --source-api-key, kept for the `launch` source (or set LAUNCH_API_KEY).
1117
+ Prefer --source-api-key.
1118
+ --dir=<value> Target local workspace directory. Defaults to cwd if it looks like a Quonfig workspace,
1119
+ otherwise ./quonfig-repo.
1120
+ --dry-run Fetch and summarize changes without writing anything
1121
+ --from=<option> (required) Legacy source to migrate from
1122
+ <options: launch|launchdarkly|flagsmith>
1123
+ --full-summary Reify the full source-side audit log into per-change git commits (author = original user,
1124
+ date = original timestamp, message = change summary). Only valid on first-run imports — pass
1125
+ --reset to re-import everything from scratch with this flag.
1126
+ --project=<value> [default: default] LaunchDarkly project key to migrate from (or set
1127
+ LAUNCHDARKLY_PROJECT_KEY). Scoped to `--from launchdarkly`; ignored by other sources.
1128
+ --push After migrating to a local dir, also push to the given --workspace on Quonfig cloud
1129
+ --recent=<value> Import only the last N changes (useful for tire-kicking)
1130
+ --reset Ignore the delta cursor and re-import everything from scratch
1131
+ --since=<value> Override the delta cursor (epoch milliseconds or ISO-8601 timestamp)
1132
+ --source-api-key=<value> API key for the legacy source. Set this, QUONFIG_MIGRATE_API_KEY, or the per-provider env
1133
+ var (LAUNCHDARKLY_API_KEY, LAUNCH_API_KEY, FLAGSMITH_API_KEY).
1134
+ --staging Hit the staging API for the source (dev-only)
1135
+ --workspace=<value> Quonfig cloud workspace slug to push to. Requires `qfg login` and is typically combined with
1136
+ --push.
1132
1137
 
1133
1138
  GLOBAL FLAGS
1134
1139
  --[no-]interactive Force interactive mode
@@ -1146,18 +1151,18 @@ DESCRIPTION
1146
1151
  and https://docs.quonfig.com/docs/migrating/troubleshooting when something goes sideways.
1147
1152
 
1148
1153
  EXAMPLES
1149
- $ qfg migrate --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-repo
1154
+ $ qfg migrate --from launchdarkly --source-api-key $LAUNCHDARKLY_API_KEY --dir ./quonfig-repo
1150
1155
 
1151
- $ qfg migrate --from launch --api-key $LAUNCH_API_KEY --workspace acme-prod --push
1156
+ $ qfg migrate --from launch --source-api-key $LAUNCH_API_KEY --workspace acme-prod --push
1152
1157
 
1153
1158
  $ qfg migrate --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-repo --reset
1154
1159
 
1155
- $ qfg migrate --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-repo --dry-run
1160
+ $ qfg migrate --from launch --source-api-key $LAUNCH_API_KEY --dir ./quonfig-repo --dry-run
1156
1161
 
1157
- $ qfg migrate --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-repo --staging
1162
+ $ qfg migrate --from launch --source-api-key $LAUNCH_API_KEY --dir ./quonfig-repo --staging
1158
1163
  ```
1159
1164
 
1160
- _See code: [src/commands/migrate.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/migrate.ts)_
1165
+ _See code: [src/commands/migrate.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/migrate.ts)_
1161
1166
 
1162
1167
  ## `qfg migrate doctor`
1163
1168
 
@@ -1195,7 +1200,7 @@ EXAMPLES
1195
1200
  $ qfg migrate doctor --json
1196
1201
  ```
1197
1202
 
1198
- _See code: [src/commands/migrate/doctor.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/migrate/doctor.ts)_
1203
+ _See code: [src/commands/migrate/doctor.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/migrate/doctor.ts)_
1199
1204
 
1200
1205
  ## `qfg migrate my-code`
1201
1206
 
@@ -1227,7 +1232,7 @@ EXAMPLES
1227
1232
  $ qfg migrate my-code --dry-run
1228
1233
  ```
1229
1234
 
1230
- _See code: [src/commands/migrate/my-code.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/migrate/my-code.ts)_
1235
+ _See code: [src/commands/migrate/my-code.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/migrate/my-code.ts)_
1231
1236
 
1232
1237
  ## `qfg migrate status`
1233
1238
 
@@ -1258,7 +1263,7 @@ EXAMPLES
1258
1263
  $ qfg migrate status --json
1259
1264
  ```
1260
1265
 
1261
- _See code: [src/commands/migrate/status.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/migrate/status.ts)_
1266
+ _See code: [src/commands/migrate/status.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/migrate/status.ts)_
1262
1267
 
1263
1268
  ## `qfg override [NAME] [VALUE]`
1264
1269
 
@@ -1313,7 +1318,7 @@ EXAMPLES
1313
1318
  $ qfg override my.flag true --env=staging
1314
1319
  ```
1315
1320
 
1316
- _See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/override.ts)_
1321
+ _See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/override.ts)_
1317
1322
 
1318
1323
  ## `qfg pull`
1319
1324
 
@@ -1361,7 +1366,7 @@ EXAMPLES
1361
1366
  $ qfg pull # uses QUONFIG_DIR env var
1362
1367
  ```
1363
1368
 
1364
- _See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/pull.ts)_
1369
+ _See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/pull.ts)_
1365
1370
 
1366
1371
  ## `qfg push`
1367
1372
 
@@ -1410,7 +1415,7 @@ EXAMPLES
1410
1415
  $ qfg push --dir ./our-config --yes
1411
1416
  ```
1412
1417
 
1413
- _See code: [src/commands/push.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/push.ts)_
1418
+ _See code: [src/commands/push.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/push.ts)_
1414
1419
 
1415
1420
  ## `qfg run [COMMAND]`
1416
1421
 
@@ -1461,7 +1466,7 @@ EXAMPLES
1461
1466
  $ qfg run --env DATABASE_URL=db.url --preserve-env --environment=staging -- npm test
1462
1467
  ```
1463
1468
 
1464
- _See code: [src/commands/run.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/run.ts)_
1469
+ _See code: [src/commands/run.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/run.ts)_
1465
1470
 
1466
1471
  ## `qfg schema NAME`
1467
1472
 
@@ -1499,7 +1504,7 @@ EXAMPLES
1499
1504
  $ qfg schema my-schema --set-json-schema=@schemas/my-schema.json --protected
1500
1505
  ```
1501
1506
 
1502
- _See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/schema.ts)_
1507
+ _See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/schema.ts)_
1503
1508
 
1504
1509
  ## `qfg sdk-key`
1505
1510
 
@@ -1526,7 +1531,7 @@ EXAMPLES
1526
1531
  $ qfg sdk-key revoke <key-id>
1527
1532
  ```
1528
1533
 
1529
- _See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/sdk-key.ts)_
1534
+ _See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/sdk-key.ts)_
1530
1535
 
1531
1536
  ## `qfg sdk-key create`
1532
1537
 
@@ -1558,7 +1563,7 @@ EXAMPLES
1558
1563
  $ qfg sdk-key create --environment staging --type browser
1559
1564
  ```
1560
1565
 
1561
- _See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/sdk-key/create.ts)_
1566
+ _See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/sdk-key/create.ts)_
1562
1567
 
1563
1568
  ## `qfg sdk-key list`
1564
1569
 
@@ -1587,7 +1592,7 @@ EXAMPLES
1587
1592
  $ qfg sdk-key list --environment production
1588
1593
  ```
1589
1594
 
1590
- _See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/sdk-key/list.ts)_
1595
+ _See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/sdk-key/list.ts)_
1591
1596
 
1592
1597
  ## `qfg sdk-key revoke KEYID`
1593
1598
 
@@ -1614,7 +1619,7 @@ EXAMPLES
1614
1619
  $ qfg sdk-key revoke a1b2c3d4-e5f6-7890-abcd-ef1234567890
1615
1620
  ```
1616
1621
 
1617
- _See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/sdk-key/revoke.ts)_
1622
+ _See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/sdk-key/revoke.ts)_
1618
1623
 
1619
1624
  ## `qfg set-default [NAME]`
1620
1625
 
@@ -1685,7 +1690,7 @@ EXAMPLES
1685
1690
  $ qfg pull && qfg config-schema
1686
1691
  ```
1687
1692
 
1688
- _See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/set-default.ts)_
1693
+ _See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/set-default.ts)_
1689
1694
 
1690
1695
  ## `qfg set-rollout [NAME]`
1691
1696
 
@@ -1762,7 +1767,7 @@ EXAMPLES
1762
1767
  $ qfg set-rollout my.variant.flag --environment production --weights "a:33,b:33,c:34" --hash-by user.id
1763
1768
  ```
1764
1769
 
1765
- _See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/set-rollout.ts)_
1770
+ _See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/set-rollout.ts)_
1766
1771
 
1767
1772
  ## `qfg sync`
1768
1773
 
@@ -1794,7 +1799,7 @@ EXAMPLES
1794
1799
  $ qfg sync --watch --dir ./our-config --interval 30
1795
1800
  ```
1796
1801
 
1797
- _See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/sync.ts)_
1802
+ _See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/sync.ts)_
1798
1803
 
1799
1804
  ## `qfg toggle [NAME]`
1800
1805
 
@@ -1896,7 +1901,7 @@ EXAMPLES
1896
1901
  $ qfg verify --json
1897
1902
  ```
1898
1903
 
1899
- _See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/verify.ts)_
1904
+ _See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/verify.ts)_
1900
1905
 
1901
1906
  ## `qfg whoami`
1902
1907
 
@@ -1919,7 +1924,7 @@ EXAMPLES
1919
1924
  $ qfg whoami
1920
1925
  ```
1921
1926
 
1922
- _See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/whoami.ts)_
1927
+ _See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/whoami.ts)_
1923
1928
 
1924
1929
  ## `qfg workspace`
1925
1930
 
@@ -1942,7 +1947,7 @@ EXAMPLES
1942
1947
  $ qfg workspace
1943
1948
  ```
1944
1949
 
1945
- _See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/workspace.ts)_
1950
+ _See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/workspace.ts)_
1946
1951
 
1947
1952
  ## `qfg workspace bootstrap`
1948
1953
 
@@ -1975,7 +1980,7 @@ EXAMPLES
1975
1980
  $ qfg workspace bootstrap --dir ./our-config --skip-validate
1976
1981
  ```
1977
1982
 
1978
- _See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/workspace/bootstrap.ts)_
1983
+ _See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/workspace/bootstrap.ts)_
1979
1984
 
1980
1985
  ## `qfg workspace create SLUG`
1981
1986
 
@@ -2009,7 +2014,7 @@ EXAMPLES
2009
2014
  $ qfg workspace create my-team --org 11111111-1111-1111-1111-111111111111
2010
2015
  ```
2011
2016
 
2012
- _See code: [src/commands/workspace/create.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/workspace/create.ts)_
2017
+ _See code: [src/commands/workspace/create.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/workspace/create.ts)_
2013
2018
 
2014
2019
  ## `qfg workspace switch [SLUG]`
2015
2020
 
@@ -2037,7 +2042,7 @@ EXAMPLES
2037
2042
  $ qfg workspace switch acme/production
2038
2043
  ```
2039
2044
 
2040
- _See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.46/src/commands/workspace/switch.ts)_
2045
+ _See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.48/src/commands/workspace/switch.ts)_
2041
2046
  <!-- commandsstop -->
2042
2047
 
2043
2048
  ## Local Development
@@ -9,10 +9,12 @@ export default class Migrate extends BaseCommand {
9
9
  'dry-run': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
10
10
  from: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
11
  'full-summary': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
12
+ project: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
13
  push: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
13
14
  recent: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
14
15
  reset: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
15
16
  since: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
17
+ 'source-api-key': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
16
18
  staging: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
17
19
  workspace: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
18
20
  };
@@ -9,7 +9,10 @@ import { PushConflictError, PushHookRejectedError } from '../util/clone-and-stac
9
9
  import { MigratorVerifyError, pushMigrationToCloud } from '../migrate/push-to-cloud.js';
10
10
  import { UnknownSourceError, getSource } from '../migrate/registry.js';
11
11
  import { NotYetImplementedError, } from '../migrate/source.js';
12
+ import { missingSourceApiKeyMessage, resolveSourceApiKey } from '../migrate/source-api-key.js';
12
13
  import { applyLaunchBaseUrl } from '../migrate/sources/launch/api.js';
14
+ import { applyLaunchDarklyBaseUrl } from '../migrate/sources/launchdarkly/api.js';
15
+ import { getLaunchDarklyRetentionHorizon, setLaunchDarklyFullSummary, setLaunchDarklyProjectKey, } from '../migrate/sources/launchdarkly.js';
13
16
  import { mintGiteaToken } from '../util/gitea-api.js';
14
17
  import { displayUrl } from '../util/git-ops.js';
15
18
  import { resolveWorkspaceUuid } from '../util/resolve-workspace.js';
@@ -22,15 +25,15 @@ export default class Migrate extends BaseCommand {
22
25
  'See https://docs.quonfig.com/docs/migrating/from-launch for the step-by-step guide,\n' +
23
26
  'and https://docs.quonfig.com/docs/migrating/troubleshooting when something goes sideways.';
24
27
  static examples = [
25
- '<%= config.bin %> <%= command.id %> --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-repo',
26
- '<%= config.bin %> <%= command.id %> --from launch --api-key $LAUNCH_API_KEY --workspace acme-prod --push',
28
+ '<%= config.bin %> <%= command.id %> --from launchdarkly --source-api-key $LAUNCHDARKLY_API_KEY --dir ./quonfig-repo',
29
+ '<%= config.bin %> <%= command.id %> --from launch --source-api-key $LAUNCH_API_KEY --workspace acme-prod --push',
27
30
  '<%= config.bin %> <%= command.id %> --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-repo --reset',
28
- '<%= config.bin %> <%= command.id %> --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-repo --dry-run',
29
- '<%= config.bin %> <%= command.id %> --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-repo --staging',
31
+ '<%= config.bin %> <%= command.id %> --from launch --source-api-key $LAUNCH_API_KEY --dir ./quonfig-repo --dry-run',
32
+ '<%= config.bin %> <%= command.id %> --from launch --source-api-key $LAUNCH_API_KEY --dir ./quonfig-repo --staging',
30
33
  ];
31
34
  static flags = {
32
35
  'api-key': Flags.string({
33
- description: 'API key for the legacy source (or set LAUNCH_API_KEY)',
36
+ description: 'Deprecated alias for --source-api-key, kept for the `launch` source (or set LAUNCH_API_KEY). Prefer --source-api-key.',
34
37
  env: 'LAUNCH_API_KEY',
35
38
  }),
36
39
  dir: Flags.string({
@@ -51,6 +54,12 @@ export default class Migrate extends BaseCommand {
51
54
  '(author = original user, date = original timestamp, message = change summary). ' +
52
55
  'Only valid on first-run imports — pass --reset to re-import everything from scratch with this flag.',
53
56
  }),
57
+ project: Flags.string({
58
+ default: 'default',
59
+ description: 'LaunchDarkly project key to migrate from (or set LAUNCHDARKLY_PROJECT_KEY). ' +
60
+ 'Scoped to `--from launchdarkly`; ignored by other sources.',
61
+ env: 'LAUNCHDARKLY_PROJECT_KEY',
62
+ }),
54
63
  push: Flags.boolean({
55
64
  default: false,
56
65
  description: 'After migrating to a local dir, also push to the given --workspace on Quonfig cloud',
@@ -65,6 +74,11 @@ export default class Migrate extends BaseCommand {
65
74
  since: Flags.string({
66
75
  description: 'Override the delta cursor (epoch milliseconds or ISO-8601 timestamp)',
67
76
  }),
77
+ 'source-api-key': Flags.string({
78
+ description: 'API key for the legacy source. Set this, QUONFIG_MIGRATE_API_KEY, or the ' +
79
+ 'per-provider env var (LAUNCHDARKLY_API_KEY, LAUNCH_API_KEY, FLAGSMITH_API_KEY).',
80
+ env: 'QUONFIG_MIGRATE_API_KEY',
81
+ }),
68
82
  staging: Flags.boolean({
69
83
  default: false,
70
84
  description: 'Hit the staging API for the source (dev-only)',
@@ -79,8 +93,19 @@ export default class Migrate extends BaseCommand {
79
93
  return this.err('`--dir` and `--workspace` are mutually exclusive unless `--push` is also passed. ' +
80
94
  'Pass `--push` to migrate locally and then push to the cloud workspace, or drop one of the flags.');
81
95
  }
82
- if (!flags['api-key']) {
83
- return this.err('--api-key is required. For --from launch you can also set LAUNCH_API_KEY in your environment.');
96
+ const sourceApiKey = resolveSourceApiKey({
97
+ apiKeyFlag: flags['api-key'],
98
+ from: flags.from,
99
+ sourceApiKeyFlag: flags['source-api-key'],
100
+ });
101
+ if (!sourceApiKey) {
102
+ return this.err(missingSourceApiKeyMessage(flags.from));
103
+ }
104
+ // --api-key is the deprecated launch-only alias (D8). Nudge non-launch users
105
+ // toward the generalized flag, but don't fail — the key still resolved.
106
+ if (flags['api-key'] && !flags['source-api-key'] && flags.from !== 'launch') {
107
+ this.warn(`--api-key is a deprecated alias scoped to the \`launch\` source. For --from ${flags.from}, ` +
108
+ 'use --source-api-key (or the QUONFIG_MIGRATE_API_KEY env var) instead.');
84
109
  }
85
110
  if (flags['full-summary'] && flags.recent !== undefined) {
86
111
  return this.err('--full-summary and --recent are incompatible: --full-summary reifies the entire audit log into git history, ' +
@@ -117,6 +142,16 @@ export default class Migrate extends BaseCommand {
117
142
  if (flags.from === 'launch') {
118
143
  applyLaunchBaseUrl(flags.staging);
119
144
  }
145
+ if (flags.from === 'launchdarkly') {
146
+ // Thread run-scoped source config in before the first API call. The base
147
+ // URL honours the LAUNCHDARKLY_API_URL escape hatch; --project (env-backed
148
+ // by LAUNCHDARKLY_PROJECT_KEY) selects which LD project to snapshot;
149
+ // --full-summary swaps the snapshot for the Phase-2 audit-log walk (the
150
+ // walk's own resume cursor lives in os.tmpdir, not in `dir`).
151
+ applyLaunchDarklyBaseUrl();
152
+ setLaunchDarklyProjectKey(flags.project);
153
+ setLaunchDarklyFullSummary(flags['full-summary']);
154
+ }
120
155
  let source;
121
156
  try {
122
157
  source = getSource(flags.from);
@@ -128,8 +163,17 @@ export default class Migrate extends BaseCommand {
128
163
  }
129
164
  let duplicateResolutionsForWarn = null;
130
165
  try {
131
- await source.validateAuth(flags['api-key']);
166
+ await source.validateAuth(sourceApiKey);
132
167
  const environments = await source.listEnvironments();
168
+ // Plan §4.1.1: tell the user the real history horizon BEFORE the slow
169
+ // Phase-2 walk starts. validateAuth populated this for LD under
170
+ // --full-summary; the message also names the Developer-plan ≤ 30 days
171
+ // ceiling explicitly when that's what we observed.
172
+ if (flags.from === 'launchdarkly' && flags['full-summary']) {
173
+ const horizon = getLaunchDarklyRetentionHorizon();
174
+ if (horizon)
175
+ this.log(`History pre-flight: ${horizon.label}`);
176
+ }
133
177
  const existing = readImportState(dir);
134
178
  const sinceEpochMs = computeSince(flags, existing);
135
179
  const changes = [];
@@ -251,6 +295,7 @@ export default class Migrate extends BaseCommand {
251
295
  warnAboutSkippedConfigs(this, source.getSkippedConfigs?.() ?? null);
252
296
  warnAboutCoercedSentinels(this, source.getCoercedSentinels?.() ?? null);
253
297
  warnAboutDuplicateResolutions(this, duplicateResolutionsForWarn);
298
+ warnAboutConversionNotes(this, source.getConversionNotes?.() ?? null);
254
299
  }
255
300
  }
256
301
  async resolvePushWorkspace(slugOrId) {
@@ -339,6 +384,21 @@ function warnAboutCoercedSentinels(cmd, coerced) {
339
384
  }
340
385
  cmd.warn(`If you want a real default for these rules, set one in the source system and re-run the migration. Full detail is also written to MIGRATION_REPORT.md.`);
341
386
  }
387
+ function warnAboutConversionNotes(cmd, notes) {
388
+ if (!notes || notes.length === 0)
389
+ return;
390
+ const rebucketed = notes.filter((n) => n.category === 'rebucketed-rollout');
391
+ if (rebucketed.length > 0) {
392
+ cmd.warn(`${rebucketed.length} flag(s)/segment(s) use a percentage rollout — LaunchDarkly and Quonfig bucket users ` +
393
+ `differently, so individual user assignments WILL change after migration (the rollout percentage is preserved). ` +
394
+ `See the "Users will be re-bucketed" section of MIGRATION_REPORT.md.`);
395
+ }
396
+ const other = notes.filter((n) => n.category !== 'rebucketed-rollout' && n.category !== 'skipped-config');
397
+ if (other.length > 0) {
398
+ cmd.warn(`${other.length} source concept(s) could not be converted exactly (dropped prerequisites, lossy individual ` +
399
+ `targets, etc.). Nothing was silently dropped — see the "Conversion notes" section of MIGRATION_REPORT.md.`);
400
+ }
401
+ }
342
402
  function warnAboutSkippedConfigs(cmd, skipped) {
343
403
  if (!skipped || skipped.total === 0)
344
404
  return;
@@ -187,6 +187,7 @@ export const applyLocalMigration = async (opts) => {
187
187
  const droppedOverrides = opts.source.getDroppedOverrides?.() ?? null;
188
188
  const skippedConfigs = opts.source.getSkippedConfigs?.() ?? null;
189
189
  const coercedSentinels = opts.source.getCoercedSentinels?.() ?? null;
190
+ const conversionNotes = opts.source.getConversionNotes?.() ?? null;
190
191
  const duplicateResolutions = resolutionEntries.length > 0 ? { entries: resolutionEntries, total: resolutionEntries.length } : null;
191
192
  const skippedTotal = (skippedConfigs?.total ?? 0) + resolutionEntries.reduce((sum, r) => sum + r.deleted.length, 0);
192
193
  const counts = buildMigrationCounts(livePaths, opts.environments.length, skippedTotal);
@@ -194,6 +195,7 @@ export const applyLocalMigration = async (opts) => {
194
195
  ...opts.reportData,
195
196
  counts,
196
197
  ...(coercedSentinels ? { coercedSentinels } : {}),
198
+ ...(conversionNotes && conversionNotes.length > 0 ? { conversionNotes } : {}),
197
199
  ...(droppedOverrides ? { droppedOverrides } : {}),
198
200
  ...(duplicateResolutions ? { duplicateResolutions } : {}),
199
201
  ...(skippedConfigs ? { skippedConfigs } : {}),
@@ -317,6 +319,7 @@ export const buildAuditFinalCommit = (opts) => ({
317
319
  const droppedOverrides = opts.source.getDroppedOverrides?.() ?? null;
318
320
  const skippedConfigs = opts.source.getSkippedConfigs?.() ?? null;
319
321
  const coercedSentinels = opts.source.getCoercedSentinels?.() ?? null;
322
+ const conversionNotes = opts.source.getConversionNotes?.() ?? null;
320
323
  const duplicateResolutions = resolutionEntries.length > 0 ? { entries: resolutionEntries, total: resolutionEntries.length } : null;
321
324
  removeQfFromGitignore(dir);
322
325
  writeImportState(dir, opts.importState);
@@ -326,6 +329,7 @@ export const buildAuditFinalCommit = (opts) => ({
326
329
  ...opts.reportData,
327
330
  counts,
328
331
  ...(coercedSentinels ? { coercedSentinels } : {}),
332
+ ...(conversionNotes && conversionNotes.length > 0 ? { conversionNotes } : {}),
329
333
  ...(droppedOverrides ? { droppedOverrides } : {}),
330
334
  ...(duplicateResolutions ? { duplicateResolutions } : {}),
331
335
  ...(skippedConfigs ? { skippedConfigs } : {}),