@apso/cli 0.43.3 → 0.44.0
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 +7 -11
- package/dist/commands/deploy.js +1 -1
- package/dist/commands/generate.js +22 -12
- package/dist/commands/migrate/generate.d.ts +3 -1
- package/dist/commands/migrate/generate.js +42 -8
- package/dist/commands/migrate/plan.d.ts +12 -0
- package/dist/commands/migrate/plan.js +88 -0
- package/dist/commands/migrate/sandbox.d.ts +11 -0
- package/dist/commands/migrate/sandbox.js +132 -0
- package/dist/commands/migrate/verify.d.ts +5 -2
- package/dist/commands/migrate/verify.js +44 -9
- package/dist/commands/migrate.d.ts +16 -3
- package/dist/commands/migrate.js +171 -96
- package/dist/lib/ddl/catalog.d.ts +21 -0
- package/dist/lib/ddl/catalog.js +58 -0
- package/dist/lib/ddl/change.d.ts +19 -0
- package/dist/lib/ddl/change.js +393 -0
- package/dist/lib/ddl/index.d.ts +80 -0
- package/dist/lib/ddl/index.js +309 -0
- package/dist/lib/ddl/migration-file.d.ts +42 -0
- package/dist/lib/ddl/migration-file.js +222 -0
- package/dist/lib/generators/go.js +3 -2
- package/dist/lib/generators/python.js +3 -2
- package/dist/lib/plan/baseline.d.ts +22 -0
- package/dist/lib/plan/baseline.js +100 -0
- package/dist/lib/plan/index.d.ts +52 -0
- package/dist/lib/plan/index.js +272 -0
- package/dist/lib/plan/prompts.d.ts +18 -0
- package/dist/lib/plan/prompts.js +77 -0
- package/dist/lib/utils/file-system.d.ts +8 -0
- package/dist/lib/utils/file-system.js +31 -1
- package/dist/lib/verify/index.d.ts +27 -9
- package/dist/lib/verify/index.js +249 -21
- package/dist/lib/verify/review.d.ts +14 -0
- package/dist/lib/verify/review.js +98 -0
- package/npm-shrinkwrap.json +2 -2
- package/oclif.manifest.json +176 -23
- package/package.json +1 -1
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.44.0",
|
|
3
3
|
"commands": {
|
|
4
4
|
"config": {
|
|
5
5
|
"id": "config",
|
|
@@ -379,7 +379,7 @@
|
|
|
379
379
|
},
|
|
380
380
|
"migrate": {
|
|
381
381
|
"id": "migrate",
|
|
382
|
-
"description": "
|
|
382
|
+
"description": "Migrate the database to this .apsorc in one step: regenerate the code, compare with the deployed schema, ask about anything ambiguous (a rename or a drop, how a field splits, what replaces a removed value), write the migration, and test it on a local copy. In a terminal it asks; for an agent it prints the open questions as JSON and exits 2, and the agent reruns it with --answer. The steps are also separate commands: apso migrate plan, generate and verify.",
|
|
383
383
|
"strict": true,
|
|
384
384
|
"pluginName": "@apso/cli",
|
|
385
385
|
"pluginAlias": "@apso/cli",
|
|
@@ -388,27 +388,65 @@
|
|
|
388
388
|
"hiddenAliases": [],
|
|
389
389
|
"examples": [
|
|
390
390
|
"$ apso migrate",
|
|
391
|
-
"$ apso migrate --
|
|
392
|
-
"$ apso migrate --
|
|
393
|
-
"$ apso migrate --sql"
|
|
391
|
+
"$ apso migrate --answer field:Contact.phone=rename:mobilePhone",
|
|
392
|
+
"$ apso migrate --seed seed.sql --check checks.sql"
|
|
394
393
|
],
|
|
395
394
|
"flags": {
|
|
396
|
-
"
|
|
397
|
-
"name": "
|
|
395
|
+
"baseline": {
|
|
396
|
+
"name": "baseline",
|
|
397
|
+
"type": "option",
|
|
398
|
+
"description": "The deployed .apsorc, the first time only. Later runs find it from the last migration",
|
|
399
|
+
"multiple": false
|
|
400
|
+
},
|
|
401
|
+
"answer": {
|
|
402
|
+
"name": "answer",
|
|
403
|
+
"type": "option",
|
|
404
|
+
"description": "Answer a question: <question id>=<option>. Repeatable.",
|
|
405
|
+
"multiple": true,
|
|
406
|
+
"default": []
|
|
407
|
+
},
|
|
408
|
+
"seed": {
|
|
409
|
+
"name": "seed",
|
|
410
|
+
"type": "option",
|
|
411
|
+
"description": "SQL file of rows to load first; the test then fails if the migration loses any",
|
|
412
|
+
"multiple": false
|
|
413
|
+
},
|
|
414
|
+
"check": {
|
|
415
|
+
"name": "check",
|
|
416
|
+
"type": "option",
|
|
417
|
+
"description": "SQL file of SELECTs with a boolean ok column, run after the migration",
|
|
418
|
+
"multiple": false
|
|
419
|
+
},
|
|
420
|
+
"accept-loss": {
|
|
421
|
+
"name": "accept-loss",
|
|
422
|
+
"type": "option",
|
|
423
|
+
"description": "A table or table.column whose seeded data may be dropped on purpose (repeatable)",
|
|
424
|
+
"multiple": true,
|
|
425
|
+
"default": []
|
|
426
|
+
},
|
|
427
|
+
"name": {
|
|
428
|
+
"name": "name",
|
|
429
|
+
"type": "option",
|
|
430
|
+
"description": "Migration name",
|
|
431
|
+
"multiple": false,
|
|
432
|
+
"default": "SchemaUpdate"
|
|
433
|
+
},
|
|
434
|
+
"skip-generate": {
|
|
435
|
+
"name": "skip-generate",
|
|
398
436
|
"type": "boolean",
|
|
399
|
-
"description": "
|
|
437
|
+
"description": "Don't regenerate code from .apsorc first",
|
|
400
438
|
"allowNo": false
|
|
401
439
|
},
|
|
402
|
-
"
|
|
403
|
-
"name": "
|
|
440
|
+
"skip-verify": {
|
|
441
|
+
"name": "skip-verify",
|
|
404
442
|
"type": "boolean",
|
|
405
|
-
"description": "
|
|
443
|
+
"description": "Write the migration without testing it",
|
|
406
444
|
"allowNo": false
|
|
407
445
|
},
|
|
408
|
-
"
|
|
409
|
-
"name": "
|
|
446
|
+
"json": {
|
|
447
|
+
"name": "json",
|
|
410
448
|
"type": "boolean",
|
|
411
|
-
"description": "
|
|
449
|
+
"description": "Print the result as JSON (the default when output is not a terminal)",
|
|
412
450
|
"allowNo": false
|
|
413
451
|
}
|
|
414
452
|
},
|
|
@@ -771,7 +809,7 @@
|
|
|
771
809
|
},
|
|
772
810
|
"migrate:generate": {
|
|
773
811
|
"id": "migrate:generate",
|
|
774
|
-
"description": "
|
|
812
|
+
"description": "Write a migration from the deployed schema to this project's .apsorc. Apso renders the SQL from the answered migration plan (apso migrate plan), including data moves and a down() that reverses them. Exits 2 while plan questions are open. The migration is a TypeORM class, an Alembic revision or a goose SQL file, by the service's language. --typeorm uses TypeORM's generator on a local PGlite database instead (TypeScript services).",
|
|
775
813
|
"strict": true,
|
|
776
814
|
"pluginName": "@apso/cli",
|
|
777
815
|
"pluginAlias": "@apso/cli",
|
|
@@ -779,14 +817,15 @@
|
|
|
779
817
|
"aliases": [],
|
|
780
818
|
"hiddenAliases": [],
|
|
781
819
|
"examples": [
|
|
782
|
-
"$ apso migrate
|
|
820
|
+
"$ apso migrate plan --answer entity:Company=rename:Organization",
|
|
821
|
+
"$ apso migrate generate",
|
|
822
|
+
"$ apso migrate generate --typeorm"
|
|
783
823
|
],
|
|
784
824
|
"flags": {
|
|
785
825
|
"baseline": {
|
|
786
826
|
"name": "baseline",
|
|
787
827
|
"type": "option",
|
|
788
|
-
"description": "The deployed .apsorc to migrate from",
|
|
789
|
-
"required": true,
|
|
828
|
+
"description": "The deployed .apsorc to migrate from. Defaults to the schema after the newest planned migration, or the .apsorc from the last commit that changed the migrations folder",
|
|
790
829
|
"multiple": false
|
|
791
830
|
},
|
|
792
831
|
"name": {
|
|
@@ -796,6 +835,19 @@
|
|
|
796
835
|
"multiple": false,
|
|
797
836
|
"default": "SchemaUpdate"
|
|
798
837
|
},
|
|
838
|
+
"plan": {
|
|
839
|
+
"name": "plan",
|
|
840
|
+
"type": "option",
|
|
841
|
+
"description": "Migration plan with the answers",
|
|
842
|
+
"multiple": false,
|
|
843
|
+
"default": ".apso/migration-plan.json"
|
|
844
|
+
},
|
|
845
|
+
"typeorm": {
|
|
846
|
+
"name": "typeorm",
|
|
847
|
+
"type": "boolean",
|
|
848
|
+
"description": "Use TypeORM's migration:generate instead of Apso's plan (no data moves)",
|
|
849
|
+
"allowNo": false
|
|
850
|
+
},
|
|
799
851
|
"json": {
|
|
800
852
|
"name": "json",
|
|
801
853
|
"type": "boolean",
|
|
@@ -805,9 +857,90 @@
|
|
|
805
857
|
},
|
|
806
858
|
"args": {}
|
|
807
859
|
},
|
|
860
|
+
"migrate:plan": {
|
|
861
|
+
"id": "migrate:plan",
|
|
862
|
+
"description": "Compare the deployed .apsorc with this one and write a migration plan. Changes whose intent is ambiguous (rename or drop, how a field splits, which value replaces a removed enum value) become questions; answer them in the plan file or with --answer. Exits 2 while questions are open.",
|
|
863
|
+
"strict": true,
|
|
864
|
+
"pluginName": "@apso/cli",
|
|
865
|
+
"pluginAlias": "@apso/cli",
|
|
866
|
+
"pluginType": "core",
|
|
867
|
+
"aliases": [],
|
|
868
|
+
"hiddenAliases": [],
|
|
869
|
+
"examples": [
|
|
870
|
+
"$ apso migrate plan",
|
|
871
|
+
"$ apso migrate plan --answer field:Contact.phone=rename:mobilePhone",
|
|
872
|
+
"$ apso migrate plan --baseline deployed.apsorc"
|
|
873
|
+
],
|
|
874
|
+
"flags": {
|
|
875
|
+
"baseline": {
|
|
876
|
+
"name": "baseline",
|
|
877
|
+
"type": "option",
|
|
878
|
+
"description": "The deployed .apsorc to migrate from. Defaults to the schema after the newest planned migration, or the .apsorc from the last commit that changed the migrations folder",
|
|
879
|
+
"multiple": false
|
|
880
|
+
},
|
|
881
|
+
"plan": {
|
|
882
|
+
"name": "plan",
|
|
883
|
+
"type": "option",
|
|
884
|
+
"description": "Plan file to read answers from and write",
|
|
885
|
+
"multiple": false,
|
|
886
|
+
"default": ".apso/migration-plan.json"
|
|
887
|
+
},
|
|
888
|
+
"answer": {
|
|
889
|
+
"name": "answer",
|
|
890
|
+
"type": "option",
|
|
891
|
+
"description": "Answer a question: <question id>=<option>. Repeatable.",
|
|
892
|
+
"multiple": true,
|
|
893
|
+
"default": []
|
|
894
|
+
},
|
|
895
|
+
"json": {
|
|
896
|
+
"name": "json",
|
|
897
|
+
"type": "boolean",
|
|
898
|
+
"description": "Print the open questions as JSON (the default when output is not a terminal)",
|
|
899
|
+
"allowNo": false
|
|
900
|
+
}
|
|
901
|
+
},
|
|
902
|
+
"args": {}
|
|
903
|
+
},
|
|
904
|
+
"migrate:sandbox": {
|
|
905
|
+
"id": "migrate:sandbox",
|
|
906
|
+
"description": "Test schema changes against a local PGlite sandbox that keeps its own snapshot of the last schema (the older flow; apso migrate is the guided one)",
|
|
907
|
+
"strict": true,
|
|
908
|
+
"pluginName": "@apso/cli",
|
|
909
|
+
"pluginAlias": "@apso/cli",
|
|
910
|
+
"pluginType": "core",
|
|
911
|
+
"aliases": [],
|
|
912
|
+
"hiddenAliases": [],
|
|
913
|
+
"examples": [
|
|
914
|
+
"$ apso migrate sandbox",
|
|
915
|
+
"$ apso migrate sandbox --apply",
|
|
916
|
+
"$ apso migrate sandbox --reset",
|
|
917
|
+
"$ apso migrate sandbox --sql"
|
|
918
|
+
],
|
|
919
|
+
"flags": {
|
|
920
|
+
"apply": {
|
|
921
|
+
"name": "apply",
|
|
922
|
+
"type": "boolean",
|
|
923
|
+
"description": "Apply the migration: update the local snapshot after a successful test",
|
|
924
|
+
"allowNo": false
|
|
925
|
+
},
|
|
926
|
+
"reset": {
|
|
927
|
+
"name": "reset",
|
|
928
|
+
"type": "boolean",
|
|
929
|
+
"description": "Reset the sandbox (clear snapshot and PGlite data)",
|
|
930
|
+
"allowNo": false
|
|
931
|
+
},
|
|
932
|
+
"sql": {
|
|
933
|
+
"name": "sql",
|
|
934
|
+
"type": "boolean",
|
|
935
|
+
"description": "Output raw SQL only (for piping to files)",
|
|
936
|
+
"allowNo": false
|
|
937
|
+
}
|
|
938
|
+
},
|
|
939
|
+
"args": {}
|
|
940
|
+
},
|
|
808
941
|
"migrate:verify": {
|
|
809
942
|
"id": "migrate:verify",
|
|
810
|
-
"description": "Run a migration on a local PGlite copy of the deployed schema, then check the database matches this project's entities (TypeScript
|
|
943
|
+
"description": "Run a migration on a local PGlite copy of the deployed schema, then check the database matches this project's entities (TypeScript), or a fresh build of its .apsorc (Python and Go, which also run down and check it gives back the deployed schema)",
|
|
811
944
|
"strict": true,
|
|
812
945
|
"pluginName": "@apso/cli",
|
|
813
946
|
"pluginAlias": "@apso/cli",
|
|
@@ -815,23 +948,43 @@
|
|
|
815
948
|
"aliases": [],
|
|
816
949
|
"hiddenAliases": [],
|
|
817
950
|
"examples": [
|
|
951
|
+
"$ apso migrate verify",
|
|
952
|
+
"$ apso migrate verify --seed seed.sql --check checks.sql",
|
|
953
|
+
"$ apso migrate verify --seed seed.sql --check checks.sql --accept-loss contact.fullName",
|
|
818
954
|
"$ apso migrate verify --baseline deployed.apsorc --migration src/migrations/1700000000000-SchemaUpdate-migration.ts"
|
|
819
955
|
],
|
|
820
956
|
"flags": {
|
|
821
957
|
"baseline": {
|
|
822
958
|
"name": "baseline",
|
|
823
959
|
"type": "option",
|
|
824
|
-
"description": "The deployed .apsorc the migration starts from",
|
|
825
|
-
"required": true,
|
|
960
|
+
"description": "The deployed .apsorc the migration starts from. Defaults to the schema saved with the migration's plan",
|
|
826
961
|
"multiple": false
|
|
827
962
|
},
|
|
828
963
|
"migration": {
|
|
829
964
|
"name": "migration",
|
|
830
965
|
"type": "option",
|
|
831
|
-
"description": "The migration file to run",
|
|
832
|
-
"required": true,
|
|
966
|
+
"description": "The migration file to run. Defaults to the newest planned migration",
|
|
833
967
|
"multiple": false
|
|
834
968
|
},
|
|
969
|
+
"seed": {
|
|
970
|
+
"name": "seed",
|
|
971
|
+
"type": "option",
|
|
972
|
+
"description": "SQL file of rows to insert into the deployed schema before the migration runs; the check then fails if the migration loses any of them",
|
|
973
|
+
"multiple": false
|
|
974
|
+
},
|
|
975
|
+
"check": {
|
|
976
|
+
"name": "check",
|
|
977
|
+
"type": "option",
|
|
978
|
+
"description": "SQL file of SELECTs run after the migration; each row must have a boolean ok (and a label naming the check), e.g. SELECT bool_and(\"firstName\" <> '') AS ok, 'every contact has a first name' AS label FROM contact",
|
|
979
|
+
"multiple": false
|
|
980
|
+
},
|
|
981
|
+
"accept-loss": {
|
|
982
|
+
"name": "accept-loss",
|
|
983
|
+
"type": "option",
|
|
984
|
+
"description": "A table or table.column whose seeded data the migration may drop on purpose (repeatable); pair it with --check to prove where the data went",
|
|
985
|
+
"multiple": true,
|
|
986
|
+
"default": []
|
|
987
|
+
},
|
|
835
988
|
"skip-build": {
|
|
836
989
|
"name": "skip-build",
|
|
837
990
|
"type": "boolean",
|