@quonfig/cli 0.0.65 → 0.0.67
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 +53 -51
- package/dist/commands/create.js +9 -0
- package/dist/commands/migrate.d.ts +1 -0
- package/dist/commands/migrate.js +10 -0
- package/dist/migrate/import-state.d.ts +3 -0
- package/dist/migrate/import-state.js +32 -0
- package/dist/migrate/key-rewriter.d.ts +82 -0
- package/dist/migrate/key-rewriter.js +190 -0
- package/dist/migrate/key-sanitize.d.ts +13 -0
- package/dist/migrate/key-sanitize.js +108 -0
- package/dist/migrate/local-write.d.ts +2 -0
- package/dist/migrate/local-write.js +15 -1
- package/dist/migrate/migration-report.d.ts +14 -0
- package/dist/migrate/migration-report.js +38 -0
- package/dist/migrate/push-to-cloud.d.ts +2 -0
- package/dist/migrate/push-to-cloud.js +23 -1
- package/dist/migrate/quonfig-target/ruleset.js +5 -1
- package/dist/migrate/sources/flagsmith/translate.js +10 -2
- package/dist/migrate/sources/launch/translate.d.ts +6 -4
- package/dist/migrate/sources/launch/translate.js +25 -5
- package/dist/migrate/sources/launchdarkly/translate.js +7 -4
- package/dist/util/policy-a-key.d.ts +26 -0
- package/dist/util/policy-a-key.js +42 -0
- package/dist/verify/standalone.d.ts +13 -1
- package/dist/verify/standalone.js +37 -29
- package/dist/verify/validate.js +21 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/oclif.manifest.json +7 -1
- package/package.json +8 -2
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.
|
|
20
|
+
@quonfig/cli/0.0.67 linux-x64 node-v24.4.1
|
|
21
21
|
$ qfg --help [COMMAND]
|
|
22
22
|
USAGE
|
|
23
23
|
$ qfg COMMAND
|
|
@@ -201,7 +201,7 @@ EXAMPLES
|
|
|
201
201
|
$ qfg activity restore my.flag --yes
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
_See code: [src/commands/activity.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
204
|
+
_See code: [src/commands/activity.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/activity.ts)_
|
|
205
205
|
|
|
206
206
|
## `qfg activity deleted`
|
|
207
207
|
|
|
@@ -230,7 +230,7 @@ EXAMPLES
|
|
|
230
230
|
$ qfg activity deleted --json
|
|
231
231
|
```
|
|
232
232
|
|
|
233
|
-
_See code: [src/commands/activity/deleted.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
233
|
+
_See code: [src/commands/activity/deleted.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/activity/deleted.ts)_
|
|
234
234
|
|
|
235
235
|
## `qfg activity feed`
|
|
236
236
|
|
|
@@ -265,7 +265,7 @@ EXAMPLES
|
|
|
265
265
|
$ qfg activity feed --json
|
|
266
266
|
```
|
|
267
267
|
|
|
268
|
-
_See code: [src/commands/activity/feed.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
268
|
+
_See code: [src/commands/activity/feed.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/activity/feed.ts)_
|
|
269
269
|
|
|
270
270
|
## `qfg activity history [NAME]`
|
|
271
271
|
|
|
@@ -299,7 +299,7 @@ EXAMPLES
|
|
|
299
299
|
$ qfg activity history request.timeout --json
|
|
300
300
|
```
|
|
301
301
|
|
|
302
|
-
_See code: [src/commands/activity/history.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
302
|
+
_See code: [src/commands/activity/history.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/activity/history.ts)_
|
|
303
303
|
|
|
304
304
|
## `qfg activity restore [NAME]`
|
|
305
305
|
|
|
@@ -338,7 +338,7 @@ EXAMPLES
|
|
|
338
338
|
$ qfg activity restore request.timeout --type config --yes
|
|
339
339
|
```
|
|
340
340
|
|
|
341
|
-
_See code: [src/commands/activity/restore.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
341
|
+
_See code: [src/commands/activity/restore.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/activity/restore.ts)_
|
|
342
342
|
|
|
343
343
|
## `qfg audit-log [NAME]`
|
|
344
344
|
|
|
@@ -366,7 +366,7 @@ EXAMPLES
|
|
|
366
366
|
$ qfg audit-log my.flag
|
|
367
367
|
```
|
|
368
368
|
|
|
369
|
-
_See code: [src/commands/audit-log.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
369
|
+
_See code: [src/commands/audit-log.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/audit-log.ts)_
|
|
370
370
|
|
|
371
371
|
## `qfg cleanup`
|
|
372
372
|
|
|
@@ -407,7 +407,7 @@ EXAMPLES
|
|
|
407
407
|
$ qfg cleanup status my.flag.key
|
|
408
408
|
```
|
|
409
409
|
|
|
410
|
-
_See code: [src/commands/cleanup.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
410
|
+
_See code: [src/commands/cleanup.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/cleanup.ts)_
|
|
411
411
|
|
|
412
412
|
## `qfg cleanup list`
|
|
413
413
|
|
|
@@ -453,7 +453,7 @@ EXAMPLES
|
|
|
453
453
|
$ qfg cleanup list --json
|
|
454
454
|
```
|
|
455
455
|
|
|
456
|
-
_See code: [src/commands/cleanup/list.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
456
|
+
_See code: [src/commands/cleanup/list.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/cleanup/list.ts)_
|
|
457
457
|
|
|
458
458
|
## `qfg cleanup remove [NAME]`
|
|
459
459
|
|
|
@@ -498,7 +498,7 @@ EXAMPLES
|
|
|
498
498
|
$ qfg cleanup remove my.flag.key --json
|
|
499
499
|
```
|
|
500
500
|
|
|
501
|
-
_See code: [src/commands/cleanup/remove.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
501
|
+
_See code: [src/commands/cleanup/remove.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/cleanup/remove.ts)_
|
|
502
502
|
|
|
503
503
|
## `qfg cleanup status [NAME]`
|
|
504
504
|
|
|
@@ -538,7 +538,7 @@ EXAMPLES
|
|
|
538
538
|
$ qfg cleanup status my.flag.key --json
|
|
539
539
|
```
|
|
540
540
|
|
|
541
|
-
_See code: [src/commands/cleanup/status.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
541
|
+
_See code: [src/commands/cleanup/status.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/cleanup/status.ts)_
|
|
542
542
|
|
|
543
543
|
## `qfg cleanup verify [NAME]`
|
|
544
544
|
|
|
@@ -584,7 +584,7 @@ EXAMPLES
|
|
|
584
584
|
$ qfg cleanup verify my.flag.key && qfg delete my.flag.key
|
|
585
585
|
```
|
|
586
586
|
|
|
587
|
-
_See code: [src/commands/cleanup/verify.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
587
|
+
_See code: [src/commands/cleanup/verify.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/cleanup/verify.ts)_
|
|
588
588
|
|
|
589
589
|
## `qfg config-schema`
|
|
590
590
|
|
|
@@ -613,7 +613,7 @@ EXAMPLES
|
|
|
613
613
|
$ qfg config-schema --json-schema # full JSON Schema document (copy into your editor)
|
|
614
614
|
```
|
|
615
615
|
|
|
616
|
-
_See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
616
|
+
_See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/config-schema.ts)_
|
|
617
617
|
|
|
618
618
|
## `qfg create NAME`
|
|
619
619
|
|
|
@@ -700,7 +700,7 @@ EXAMPLES
|
|
|
700
700
|
$ qfg set-rollout my.new.flag --environment production --true-percent 20
|
|
701
701
|
```
|
|
702
702
|
|
|
703
|
-
_See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
703
|
+
_See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/create.ts)_
|
|
704
704
|
|
|
705
705
|
## `qfg delete NAME`
|
|
706
706
|
|
|
@@ -746,7 +746,7 @@ EXAMPLES
|
|
|
746
746
|
$ qfg delete my.config --yes
|
|
747
747
|
```
|
|
748
748
|
|
|
749
|
-
_See code: [src/commands/delete.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
749
|
+
_See code: [src/commands/delete.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/delete.ts)_
|
|
750
750
|
|
|
751
751
|
## `qfg flag info [NAME]`
|
|
752
752
|
|
|
@@ -950,7 +950,7 @@ EXAMPLES
|
|
|
950
950
|
$ qfg generate --targets node-ts -o ./dist # combine with targets
|
|
951
951
|
```
|
|
952
952
|
|
|
953
|
-
_See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
953
|
+
_See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/generate.ts)_
|
|
954
954
|
|
|
955
955
|
## `qfg generate-new-hex-key`
|
|
956
956
|
|
|
@@ -973,7 +973,7 @@ EXAMPLES
|
|
|
973
973
|
$ qfg generate-new-hex-key
|
|
974
974
|
```
|
|
975
975
|
|
|
976
|
-
_See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
976
|
+
_See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/generate-new-hex-key.ts)_
|
|
977
977
|
|
|
978
978
|
## `qfg get [NAME]`
|
|
979
979
|
|
|
@@ -1005,7 +1005,7 @@ EXAMPLES
|
|
|
1005
1005
|
$ qfg get my.config.name --environment=production
|
|
1006
1006
|
```
|
|
1007
1007
|
|
|
1008
|
-
_See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1008
|
+
_See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/get.ts)_
|
|
1009
1009
|
|
|
1010
1010
|
## `qfg history NAME`
|
|
1011
1011
|
|
|
@@ -1031,7 +1031,7 @@ EXAMPLES
|
|
|
1031
1031
|
$ qfg history my.flag
|
|
1032
1032
|
```
|
|
1033
1033
|
|
|
1034
|
-
_See code: [src/commands/history.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1034
|
+
_See code: [src/commands/history.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/history.ts)_
|
|
1035
1035
|
|
|
1036
1036
|
## `qfg info [NAME]`
|
|
1037
1037
|
|
|
@@ -1079,7 +1079,7 @@ EXAMPLES
|
|
|
1079
1079
|
$ qfg info my.config.name --exclude-evaluations # skip 24h stats
|
|
1080
1080
|
```
|
|
1081
1081
|
|
|
1082
|
-
_See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1082
|
+
_See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/info.ts)_
|
|
1083
1083
|
|
|
1084
1084
|
## `qfg init [DIRECTORY]`
|
|
1085
1085
|
|
|
@@ -1119,7 +1119,7 @@ EXAMPLES
|
|
|
1119
1119
|
$ qfg init --dry-run
|
|
1120
1120
|
```
|
|
1121
1121
|
|
|
1122
|
-
_See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1122
|
+
_See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/init.ts)_
|
|
1123
1123
|
|
|
1124
1124
|
## `qfg interactive`
|
|
1125
1125
|
|
|
@@ -1149,7 +1149,7 @@ EXAMPLES
|
|
|
1149
1149
|
$ qfg
|
|
1150
1150
|
```
|
|
1151
1151
|
|
|
1152
|
-
_See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1152
|
+
_See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/interactive.ts)_
|
|
1153
1153
|
|
|
1154
1154
|
## `qfg list`
|
|
1155
1155
|
|
|
@@ -1189,7 +1189,7 @@ EXAMPLES
|
|
|
1189
1189
|
$ qfg list --feature-flags
|
|
1190
1190
|
```
|
|
1191
1191
|
|
|
1192
|
-
_See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1192
|
+
_See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/list.ts)_
|
|
1193
1193
|
|
|
1194
1194
|
## `qfg log`
|
|
1195
1195
|
|
|
@@ -1214,7 +1214,7 @@ EXAMPLES
|
|
|
1214
1214
|
$ qfg log --limit 5
|
|
1215
1215
|
```
|
|
1216
1216
|
|
|
1217
|
-
_See code: [src/commands/log.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1217
|
+
_See code: [src/commands/log.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/log.ts)_
|
|
1218
1218
|
|
|
1219
1219
|
## `qfg log-level NAME`
|
|
1220
1220
|
|
|
@@ -1279,7 +1279,7 @@ EXAMPLES
|
|
|
1279
1279
|
$ qfg log-level log-level.my-app --target=Chatty --value=INFO --environment=production
|
|
1280
1280
|
```
|
|
1281
1281
|
|
|
1282
|
-
_See code: [src/commands/log-level.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1282
|
+
_See code: [src/commands/log-level.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/log-level.ts)_
|
|
1283
1283
|
|
|
1284
1284
|
## `qfg login`
|
|
1285
1285
|
|
|
@@ -1304,7 +1304,7 @@ EXAMPLES
|
|
|
1304
1304
|
$ qfg login --profile myprofile
|
|
1305
1305
|
```
|
|
1306
1306
|
|
|
1307
|
-
_See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1307
|
+
_See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/login.ts)_
|
|
1308
1308
|
|
|
1309
1309
|
## `qfg logout`
|
|
1310
1310
|
|
|
@@ -1327,7 +1327,7 @@ EXAMPLES
|
|
|
1327
1327
|
$ qfg logout
|
|
1328
1328
|
```
|
|
1329
1329
|
|
|
1330
|
-
_See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1330
|
+
_See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/logout.ts)_
|
|
1331
1331
|
|
|
1332
1332
|
## `qfg migrate`
|
|
1333
1333
|
|
|
@@ -1337,7 +1337,7 @@ Migrate flags and configs from a legacy feature-flag system into a Quonfig works
|
|
|
1337
1337
|
USAGE
|
|
1338
1338
|
$ qfg migrate --from launch|launchdarkly|flagsmith [--json] [--interactive] [--no-color] [--verbose]
|
|
1339
1339
|
[--api-key <value>] [--dir <value>] [--dry-run] [--full-summary] [--project <value>] [--push] [--recent <value>]
|
|
1340
|
-
[--reset] [--since <value>] [--source-api-key <value>] [--staging] [--workspace <value>]
|
|
1340
|
+
[--reset] [--since <value>] [--source-api-key <value>] [--staging] [--strict-keys] [--workspace <value>]
|
|
1341
1341
|
|
|
1342
1342
|
FLAGS
|
|
1343
1343
|
--api-key=<value> Deprecated alias for --source-api-key, kept for the `launch` source (or set LAUNCH_API_KEY).
|
|
@@ -1360,6 +1360,8 @@ FLAGS
|
|
|
1360
1360
|
--source-api-key=<value> API key for the legacy source. Set this, QUONFIG_MIGRATE_API_KEY, or the per-provider env
|
|
1361
1361
|
var (LAUNCHDARKLY_API_KEY, LAUNCH_API_KEY, FLAGSMITH_API_KEY).
|
|
1362
1362
|
--staging Hit the staging API for the source (dev-only)
|
|
1363
|
+
--strict-keys Refuse to migrate if any source key would need rewriting to satisfy Quonfig key rules
|
|
1364
|
+
(Policy A), instead of rewriting it. Use when you require byte-identical keys.
|
|
1363
1365
|
--workspace=<value> Quonfig cloud workspace slug to push to. Requires `qfg login` and is typically combined with
|
|
1364
1366
|
--push.
|
|
1365
1367
|
|
|
@@ -1390,7 +1392,7 @@ EXAMPLES
|
|
|
1390
1392
|
$ qfg migrate --from launch --source-api-key $LAUNCH_API_KEY --dir ./quonfig-repo --staging
|
|
1391
1393
|
```
|
|
1392
1394
|
|
|
1393
|
-
_See code: [src/commands/migrate.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1395
|
+
_See code: [src/commands/migrate.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/migrate.ts)_
|
|
1394
1396
|
|
|
1395
1397
|
## `qfg migrate doctor`
|
|
1396
1398
|
|
|
@@ -1428,7 +1430,7 @@ EXAMPLES
|
|
|
1428
1430
|
$ qfg migrate doctor --json
|
|
1429
1431
|
```
|
|
1430
1432
|
|
|
1431
|
-
_See code: [src/commands/migrate/doctor.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1433
|
+
_See code: [src/commands/migrate/doctor.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/migrate/doctor.ts)_
|
|
1432
1434
|
|
|
1433
1435
|
## `qfg migrate my-code`
|
|
1434
1436
|
|
|
@@ -1460,7 +1462,7 @@ EXAMPLES
|
|
|
1460
1462
|
$ qfg migrate my-code --dry-run
|
|
1461
1463
|
```
|
|
1462
1464
|
|
|
1463
|
-
_See code: [src/commands/migrate/my-code.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1465
|
+
_See code: [src/commands/migrate/my-code.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/migrate/my-code.ts)_
|
|
1464
1466
|
|
|
1465
1467
|
## `qfg migrate status`
|
|
1466
1468
|
|
|
@@ -1491,7 +1493,7 @@ EXAMPLES
|
|
|
1491
1493
|
$ qfg migrate status --json
|
|
1492
1494
|
```
|
|
1493
1495
|
|
|
1494
|
-
_See code: [src/commands/migrate/status.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1496
|
+
_See code: [src/commands/migrate/status.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/migrate/status.ts)_
|
|
1495
1497
|
|
|
1496
1498
|
## `qfg override [NAME] [VALUE]`
|
|
1497
1499
|
|
|
@@ -1546,7 +1548,7 @@ EXAMPLES
|
|
|
1546
1548
|
$ qfg override my.flag true --env=staging
|
|
1547
1549
|
```
|
|
1548
1550
|
|
|
1549
|
-
_See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1551
|
+
_See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/override.ts)_
|
|
1550
1552
|
|
|
1551
1553
|
## `qfg pull`
|
|
1552
1554
|
|
|
@@ -1594,7 +1596,7 @@ EXAMPLES
|
|
|
1594
1596
|
$ qfg pull # uses QUONFIG_DIR env var
|
|
1595
1597
|
```
|
|
1596
1598
|
|
|
1597
|
-
_See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1599
|
+
_See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/pull.ts)_
|
|
1598
1600
|
|
|
1599
1601
|
## `qfg push`
|
|
1600
1602
|
|
|
@@ -1643,7 +1645,7 @@ EXAMPLES
|
|
|
1643
1645
|
$ qfg push --dir ./our-config --yes
|
|
1644
1646
|
```
|
|
1645
1647
|
|
|
1646
|
-
_See code: [src/commands/push.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1648
|
+
_See code: [src/commands/push.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/push.ts)_
|
|
1647
1649
|
|
|
1648
1650
|
## `qfg run [COMMAND]`
|
|
1649
1651
|
|
|
@@ -1694,7 +1696,7 @@ EXAMPLES
|
|
|
1694
1696
|
$ qfg run --env DATABASE_URL=db.url --preserve-env --environment=staging -- npm test
|
|
1695
1697
|
```
|
|
1696
1698
|
|
|
1697
|
-
_See code: [src/commands/run.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1699
|
+
_See code: [src/commands/run.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/run.ts)_
|
|
1698
1700
|
|
|
1699
1701
|
## `qfg schema NAME`
|
|
1700
1702
|
|
|
@@ -1732,7 +1734,7 @@ EXAMPLES
|
|
|
1732
1734
|
$ qfg schema my-schema --set-json-schema=@schemas/my-schema.json --protected
|
|
1733
1735
|
```
|
|
1734
1736
|
|
|
1735
|
-
_See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1737
|
+
_See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/schema.ts)_
|
|
1736
1738
|
|
|
1737
1739
|
## `qfg sdk-key`
|
|
1738
1740
|
|
|
@@ -1759,7 +1761,7 @@ EXAMPLES
|
|
|
1759
1761
|
$ qfg sdk-key revoke <key-id>
|
|
1760
1762
|
```
|
|
1761
1763
|
|
|
1762
|
-
_See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1764
|
+
_See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/sdk-key.ts)_
|
|
1763
1765
|
|
|
1764
1766
|
## `qfg sdk-key create`
|
|
1765
1767
|
|
|
@@ -1791,7 +1793,7 @@ EXAMPLES
|
|
|
1791
1793
|
$ qfg sdk-key create --environment staging --type browser
|
|
1792
1794
|
```
|
|
1793
1795
|
|
|
1794
|
-
_See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1796
|
+
_See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/sdk-key/create.ts)_
|
|
1795
1797
|
|
|
1796
1798
|
## `qfg sdk-key list`
|
|
1797
1799
|
|
|
@@ -1820,7 +1822,7 @@ EXAMPLES
|
|
|
1820
1822
|
$ qfg sdk-key list --environment production
|
|
1821
1823
|
```
|
|
1822
1824
|
|
|
1823
|
-
_See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1825
|
+
_See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/sdk-key/list.ts)_
|
|
1824
1826
|
|
|
1825
1827
|
## `qfg sdk-key revoke KEYID`
|
|
1826
1828
|
|
|
@@ -1847,7 +1849,7 @@ EXAMPLES
|
|
|
1847
1849
|
$ qfg sdk-key revoke a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
|
1848
1850
|
```
|
|
1849
1851
|
|
|
1850
|
-
_See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1852
|
+
_See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/sdk-key/revoke.ts)_
|
|
1851
1853
|
|
|
1852
1854
|
## `qfg serve`
|
|
1853
1855
|
|
|
@@ -1904,7 +1906,7 @@ EXAMPLES
|
|
|
1904
1906
|
$ qfg serve --port 6581 --frontend-sdk-key PUBLIC_KEY
|
|
1905
1907
|
```
|
|
1906
1908
|
|
|
1907
|
-
_See code: [src/commands/serve.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1909
|
+
_See code: [src/commands/serve.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/serve.ts)_
|
|
1908
1910
|
|
|
1909
1911
|
## `qfg set-default [NAME]`
|
|
1910
1912
|
|
|
@@ -1975,7 +1977,7 @@ EXAMPLES
|
|
|
1975
1977
|
$ qfg pull && qfg config-schema
|
|
1976
1978
|
```
|
|
1977
1979
|
|
|
1978
|
-
_See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
1980
|
+
_See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/set-default.ts)_
|
|
1979
1981
|
|
|
1980
1982
|
## `qfg set-rollout [NAME]`
|
|
1981
1983
|
|
|
@@ -2052,7 +2054,7 @@ EXAMPLES
|
|
|
2052
2054
|
$ qfg set-rollout my.variant.flag --environment production --weights "a:33,b:33,c:34" --hash-by user.id
|
|
2053
2055
|
```
|
|
2054
2056
|
|
|
2055
|
-
_See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
2057
|
+
_See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/set-rollout.ts)_
|
|
2056
2058
|
|
|
2057
2059
|
## `qfg sync`
|
|
2058
2060
|
|
|
@@ -2084,7 +2086,7 @@ EXAMPLES
|
|
|
2084
2086
|
$ qfg sync --watch --dir ./our-config --interval 30
|
|
2085
2087
|
```
|
|
2086
2088
|
|
|
2087
|
-
_See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
2089
|
+
_See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/sync.ts)_
|
|
2088
2090
|
|
|
2089
2091
|
## `qfg toggle [NAME]`
|
|
2090
2092
|
|
|
@@ -2186,7 +2188,7 @@ EXAMPLES
|
|
|
2186
2188
|
$ qfg verify --json
|
|
2187
2189
|
```
|
|
2188
2190
|
|
|
2189
|
-
_See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
2191
|
+
_See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/verify.ts)_
|
|
2190
2192
|
|
|
2191
2193
|
## `qfg whoami`
|
|
2192
2194
|
|
|
@@ -2209,7 +2211,7 @@ EXAMPLES
|
|
|
2209
2211
|
$ qfg whoami
|
|
2210
2212
|
```
|
|
2211
2213
|
|
|
2212
|
-
_See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
2214
|
+
_See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/whoami.ts)_
|
|
2213
2215
|
|
|
2214
2216
|
## `qfg workspace`
|
|
2215
2217
|
|
|
@@ -2232,7 +2234,7 @@ EXAMPLES
|
|
|
2232
2234
|
$ qfg workspace
|
|
2233
2235
|
```
|
|
2234
2236
|
|
|
2235
|
-
_See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
2237
|
+
_See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/workspace.ts)_
|
|
2236
2238
|
|
|
2237
2239
|
## `qfg workspace bootstrap`
|
|
2238
2240
|
|
|
@@ -2265,7 +2267,7 @@ EXAMPLES
|
|
|
2265
2267
|
$ qfg workspace bootstrap --dir ./our-config --skip-validate
|
|
2266
2268
|
```
|
|
2267
2269
|
|
|
2268
|
-
_See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
2270
|
+
_See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/workspace/bootstrap.ts)_
|
|
2269
2271
|
|
|
2270
2272
|
## `qfg workspace create SLUG`
|
|
2271
2273
|
|
|
@@ -2299,7 +2301,7 @@ EXAMPLES
|
|
|
2299
2301
|
$ qfg workspace create my-team --org 11111111-1111-1111-1111-111111111111
|
|
2300
2302
|
```
|
|
2301
2303
|
|
|
2302
|
-
_See code: [src/commands/workspace/create.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
2304
|
+
_See code: [src/commands/workspace/create.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/workspace/create.ts)_
|
|
2303
2305
|
|
|
2304
2306
|
## `qfg workspace switch [SLUG]`
|
|
2305
2307
|
|
|
@@ -2327,7 +2329,7 @@ EXAMPLES
|
|
|
2327
2329
|
$ qfg workspace switch acme/production
|
|
2328
2330
|
```
|
|
2329
2331
|
|
|
2330
|
-
_See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.
|
|
2332
|
+
_See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.67/src/commands/workspace/switch.ts)_
|
|
2331
2333
|
<!-- commandsstop -->
|
|
2332
2334
|
|
|
2333
2335
|
## Local Development
|
package/dist/commands/create.js
CHANGED
|
@@ -8,6 +8,7 @@ import { mapConfigValueToDto, mapValueTypeToString } from '../util/config-value-
|
|
|
8
8
|
import { makeConfidentialValue } from '../util/encryption.js';
|
|
9
9
|
import { writeStoredConfigToWorkspace } from '../util/local-config-writer.js';
|
|
10
10
|
import { LOG_LEVELS, LOG_LEVEL_KEY_PREFIX, isLogLevel } from '../util/log-levels.js';
|
|
11
|
+
import { policyAKeyError } from '../util/policy-a-key.js';
|
|
11
12
|
import secretFlags, { parsedSecretFlags } from '../util/secret-flags.js';
|
|
12
13
|
export default class Create extends APICommand {
|
|
13
14
|
static args = {
|
|
@@ -68,6 +69,14 @@ When this flag has done its job, mark readyForCleanup: true in the UI and run \`
|
|
|
68
69
|
};
|
|
69
70
|
async run() {
|
|
70
71
|
const { args, flags } = await this.parse(Create);
|
|
72
|
+
// qfg-6na9.2: hard-enforce Policy A client-side before any network/prompt,
|
|
73
|
+
// so a bad key fails fast here instead of a 4xx from the server (which
|
|
74
|
+
// hard-enforces the same rule at create via PolicyAKeySchema, qfg-6na9.1).
|
|
75
|
+
// Covers all three creation paths below (config / boolean-flag / log-level).
|
|
76
|
+
const keyError = policyAKeyError(args.name);
|
|
77
|
+
if (keyError) {
|
|
78
|
+
return this.err(`Invalid key "${args.name}": ${keyError}`, { key: args.name, phase: 'validation' });
|
|
79
|
+
}
|
|
71
80
|
if (flags.type === 'boolean-flag') {
|
|
72
81
|
return this.createBooleanFlag(args, flags.value);
|
|
73
82
|
}
|
|
@@ -16,6 +16,7 @@ export default class Migrate extends BaseCommand {
|
|
|
16
16
|
since: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
17
17
|
'source-api-key': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
18
18
|
staging: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
19
|
+
'strict-keys': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
19
20
|
workspace: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
20
21
|
};
|
|
21
22
|
run(): Promise<JsonObj | void>;
|
package/dist/commands/migrate.js
CHANGED
|
@@ -3,6 +3,7 @@ import fs from 'node:fs';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { BaseCommand } from '../index.js';
|
|
5
5
|
import { CrossSourceError, assertSourceMatches, readImportState } from '../migrate/import-state.js';
|
|
6
|
+
import { StrictKeysError } from '../migrate/key-rewriter.js';
|
|
6
7
|
import { applyLocalMigration, MigratorKeyCollisionError } from '../migrate/local-write.js';
|
|
7
8
|
import { buildPushConflictSuggestion } from '../migrate/migrate-suggestion.js';
|
|
8
9
|
import { migrationReportPath } from '../migrate/migration-report.js';
|
|
@@ -89,6 +90,11 @@ export default class Migrate extends BaseCommand {
|
|
|
89
90
|
default: false,
|
|
90
91
|
description: 'Hit the staging API for the source (dev-only)',
|
|
91
92
|
}),
|
|
93
|
+
'strict-keys': Flags.boolean({
|
|
94
|
+
default: false,
|
|
95
|
+
description: 'Refuse to migrate if any source key would need rewriting to satisfy Quonfig key rules ' +
|
|
96
|
+
'(Policy A), instead of rewriting it. Use when you require byte-identical keys.',
|
|
97
|
+
}),
|
|
92
98
|
workspace: Flags.string({
|
|
93
99
|
description: 'Quonfig cloud workspace slug to push to. Requires `qfg login` and is typically combined with --push.',
|
|
94
100
|
}),
|
|
@@ -265,6 +271,7 @@ export default class Migrate extends BaseCommand {
|
|
|
265
271
|
remoteUrl: repoUrl,
|
|
266
272
|
reportData: buildReportData(flags.from),
|
|
267
273
|
source,
|
|
274
|
+
strictKeys: flags['strict-keys'],
|
|
268
275
|
});
|
|
269
276
|
duplicateResolutionsForWarn = result.duplicateResolutions;
|
|
270
277
|
this.log(result.committed
|
|
@@ -313,6 +320,7 @@ export default class Migrate extends BaseCommand {
|
|
|
313
320
|
localDir: dir,
|
|
314
321
|
reportData: buildReportData(flags.from),
|
|
315
322
|
source,
|
|
323
|
+
strictKeys: flags['strict-keys'],
|
|
316
324
|
});
|
|
317
325
|
duplicateResolutionsForWarn = localResult.duplicateResolutions;
|
|
318
326
|
this.log(localResult.committed
|
|
@@ -334,6 +342,8 @@ export default class Migrate extends BaseCommand {
|
|
|
334
342
|
return this.err(error.message);
|
|
335
343
|
if (error instanceof MigratorKeyCollisionError)
|
|
336
344
|
return this.err(error.message);
|
|
345
|
+
if (error instanceof StrictKeysError)
|
|
346
|
+
return this.err(error.message);
|
|
337
347
|
throw error;
|
|
338
348
|
}
|
|
339
349
|
finally {
|
|
@@ -10,5 +10,8 @@ export declare class CrossSourceError extends Error {
|
|
|
10
10
|
}
|
|
11
11
|
export declare function writeImportState(outputDir: string, state: ImportState): void;
|
|
12
12
|
export declare function readImportState(outputDir: string): ImportState | null;
|
|
13
|
+
export declare function writeKeyPlan(outputDir: string, keys: Record<string, string>): void;
|
|
14
|
+
/** The persisted plan, or null when absent/unreadable (treat as first run). */
|
|
15
|
+
export declare function readKeyPlan(outputDir: string): null | Record<string, string>;
|
|
13
16
|
export declare function assertSourceMatches(outputDir: string, requestedSource: string): void;
|
|
14
17
|
export declare function removeQfFromGitignore(outputDir: string): void;
|
|
@@ -35,6 +35,38 @@ export function readImportState(outputDir) {
|
|
|
35
35
|
return null;
|
|
36
36
|
return parsed;
|
|
37
37
|
}
|
|
38
|
+
function keyPlanPath(outputDir) {
|
|
39
|
+
return path.join(outputDir, '.qf', 'key-plan.json');
|
|
40
|
+
}
|
|
41
|
+
export function writeKeyPlan(outputDir, keys) {
|
|
42
|
+
const filePath = keyPlanPath(outputDir);
|
|
43
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
44
|
+
const sorted = {};
|
|
45
|
+
for (const source of Object.keys(keys).sort())
|
|
46
|
+
sorted[source] = keys[source];
|
|
47
|
+
const serialized = { keys: sorted, version: 1 };
|
|
48
|
+
fs.writeFileSync(filePath, JSON.stringify(serialized, null, 2) + '\n', 'utf8');
|
|
49
|
+
}
|
|
50
|
+
/** The persisted plan, or null when absent/unreadable (treat as first run). */
|
|
51
|
+
export function readKeyPlan(outputDir) {
|
|
52
|
+
const filePath = keyPlanPath(outputDir);
|
|
53
|
+
if (!fs.existsSync(filePath))
|
|
54
|
+
return null;
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
57
|
+
if (typeof parsed?.keys !== 'object' || parsed.keys === null || Array.isArray(parsed.keys))
|
|
58
|
+
return null;
|
|
59
|
+
const out = {};
|
|
60
|
+
for (const [source, final] of Object.entries(parsed.keys)) {
|
|
61
|
+
if (typeof final === 'string')
|
|
62
|
+
out[source] = final;
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
38
70
|
export function assertSourceMatches(outputDir, requestedSource) {
|
|
39
71
|
const state = readImportState(outputDir);
|
|
40
72
|
if (!state)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export interface KeyRewrite {
|
|
2
|
+
/** The Policy-A-valid, workspace-unique key it was rewritten to. */
|
|
3
|
+
final: string;
|
|
4
|
+
/** Why it changed (sanitize reasons + a disambiguation note when applicable). */
|
|
5
|
+
reasons: string[];
|
|
6
|
+
/** The original source-system key. */
|
|
7
|
+
source: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function resetKeyRewriter(): void;
|
|
10
|
+
/**
|
|
11
|
+
* Seed the rewriter with the complete source->final map persisted by previous
|
|
12
|
+
* runs. Every persisted final is immediately marked taken (case-insensitively)
|
|
13
|
+
* so keys planned later this run can never claim one. Call after
|
|
14
|
+
* `resetKeyRewriter()` and before `planKeyRewrites()` — `planKeyRewritesForChanges`
|
|
15
|
+
* does this ordering for you.
|
|
16
|
+
*/
|
|
17
|
+
export declare function seedPersistedKeyPlan(keys: Readonly<Record<string, string>>): void;
|
|
18
|
+
/**
|
|
19
|
+
* Pre-pass: compute the final key for every source key. Three passes, each
|
|
20
|
+
* sorted so every assignment is deterministic and independent of the order
|
|
21
|
+
* changes were fetched in:
|
|
22
|
+
*
|
|
23
|
+
* 0. Keys mapped by a PREVIOUS run keep their persisted final verbatim (see
|
|
24
|
+
* `seedPersistedKeyPlan`) — full and delta runs must resolve identically.
|
|
25
|
+
* 1. Keys that are ALREADY fully valid (sanitize is an identity: they pass
|
|
26
|
+
* Policy A and the FS-floor) claim their own names FIRST and are never
|
|
27
|
+
* renamed to make room for sanitized junk — customer code calling
|
|
28
|
+
* get("my-flag") must keep resolving to the same flag even when a source
|
|
29
|
+
* key like "my flag" sanitizes to the same name. If two VALID keys
|
|
30
|
+
* collide case-insensitively ("Foo"/"foo" — a genuine source conflict the
|
|
31
|
+
* FS-floor hard-rejects), the lexicographically-first one keeps its name
|
|
32
|
+
* and the other is suffixed.
|
|
33
|
+
* 2. Keys that needed sanitizing then disambiguate AROUND the valid ones
|
|
34
|
+
* (-2, -3, ...).
|
|
35
|
+
*/
|
|
36
|
+
export declare function planKeyRewrites(sourceKeys: Iterable<string>): void;
|
|
37
|
+
/**
|
|
38
|
+
* The final key for `sourceKey`. Uses the planned map when present, then the
|
|
39
|
+
* PERSISTED map (a delta run's flag can reference a segment that was migrated
|
|
40
|
+
* in the full run but is absent from the delta's change set), else a pure
|
|
41
|
+
* sanitize (no disambiguation, no mutation) as a safe fallback.
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolveKey(sourceKey: string): string;
|
|
44
|
+
/** Every key that was actually rewritten (conforming keys are omitted). */
|
|
45
|
+
export declare function getKeyRewrites(): KeyRewrite[];
|
|
46
|
+
/**
|
|
47
|
+
* The COMPLETE source->final map to persist to `.qf/key-plan.json`: every key
|
|
48
|
+
* planned this run (unchanged ones included) merged over everything persisted
|
|
49
|
+
* by previous runs, sorted by source key for stable on-disk diffs.
|
|
50
|
+
*/
|
|
51
|
+
export declare function getFullKeyPlan(): Record<string, string>;
|
|
52
|
+
/**
|
|
53
|
+
* Run-level pre-pass: reset the rewriter, seed the persisted plan from any
|
|
54
|
+
* previous run, and plan every source key BEFORE any change is translated, so
|
|
55
|
+
* both key-definition and by-key reference sites resolve against the same
|
|
56
|
+
* fully-disambiguated map. Structurally typed on `{key?}` to stay decoupled
|
|
57
|
+
* from LegacyChange.
|
|
58
|
+
*/
|
|
59
|
+
export declare function planKeyRewritesForChanges(changes: ReadonlyArray<{
|
|
60
|
+
key?: string;
|
|
61
|
+
}>, persistedKeys?: Readonly<Record<string, string>>): void;
|
|
62
|
+
/**
|
|
63
|
+
* `--strict-keys` escape hatch: refuse to migrate if any source key would need
|
|
64
|
+
* rewriting, so a customer who requires byte-identical keys can clean up the
|
|
65
|
+
* source first instead of accepting the (reported) rewrites.
|
|
66
|
+
*/
|
|
67
|
+
export declare class StrictKeysError extends Error {
|
|
68
|
+
readonly rewrites: KeyRewrite[];
|
|
69
|
+
constructor(rewrites: KeyRewrite[]);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Plan the rewrites for a run and, when `strict`, throw `StrictKeysError` if any
|
|
73
|
+
* key would be rewritten. Call once at the top of each migrate orchestrator
|
|
74
|
+
* before translating. `persistedKeys` (from `readKeyPlan`) makes previously
|
|
75
|
+
* mapped keys resolve exactly as they did on the run that mapped them.
|
|
76
|
+
*/
|
|
77
|
+
export declare function preflightKeyRewrites(changes: ReadonlyArray<{
|
|
78
|
+
key?: string;
|
|
79
|
+
}>, opts?: {
|
|
80
|
+
persistedKeys?: Readonly<Record<string, string>>;
|
|
81
|
+
strict?: boolean;
|
|
82
|
+
}): void;
|