@reventlessdev/reventless-seed 1.0.0-alpha.4 → 1.0.0-alpha.5

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 (73) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/lib/bs/.compiler.log +2 -2
  3. package/lib/bs/.sourcedirs.json +1 -0
  4. package/lib/bs/ReventlessSeed.cmi +0 -0
  5. package/lib/bs/ReventlessSeed.cmt +0 -0
  6. package/lib/bs/ReventlessSeed.mlmap +1 -0
  7. package/lib/bs/compiler-info.json +2 -2
  8. package/lib/bs/src/Seed-ReventlessSeed.cmi +0 -0
  9. package/lib/bs/src/Seed-ReventlessSeed.cmt +0 -0
  10. package/lib/bs/src/Seed.ast +0 -0
  11. package/lib/bs/src/Seed.res +4 -2
  12. package/lib/bs/src/Seed_Client-ReventlessSeed.cmt +0 -0
  13. package/lib/bs/src/Seed_Connect-ReventlessSeed.cmi +0 -0
  14. package/lib/bs/src/Seed_Connect-ReventlessSeed.cmj +0 -0
  15. package/lib/bs/src/Seed_Connect-ReventlessSeed.cmt +0 -0
  16. package/lib/bs/src/Seed_Connect.ast +0 -0
  17. package/lib/bs/src/Seed_Connect.res +49 -11
  18. package/lib/bs/src/Seed_Connect.res.mjs +24 -3
  19. package/lib/bs/src/Seed_Prompt-ReventlessSeed.cmt +0 -0
  20. package/lib/bs/src/Seed_Random-ReventlessSeed.cmt +0 -0
  21. package/lib/bs/src/Seed_Runner-ReventlessSeed.cmi +0 -0
  22. package/lib/bs/src/Seed_Runner-ReventlessSeed.cmt +0 -0
  23. package/lib/bs/src/Seed_Types-ReventlessSeed.cmt +0 -0
  24. package/lib/bs/src/Seed_Upload-ReventlessSeed.cmi +0 -0
  25. package/lib/bs/src/Seed_Upload-ReventlessSeed.cmj +0 -0
  26. package/lib/bs/src/Seed_Upload-ReventlessSeed.cmt +0 -0
  27. package/lib/bs/src/Seed_Upload.ast +0 -0
  28. package/lib/bs/src/Seed_Upload.res +59 -0
  29. package/lib/bs/src/Seed_Upload.res.mjs +29 -1
  30. package/lib/bs/tests/UploadEndpointResolutionTest-ReventlessSeed.cmi +0 -0
  31. package/lib/bs/tests/UploadEndpointResolutionTest-ReventlessSeed.cmj +0 -0
  32. package/lib/bs/tests/UploadEndpointResolutionTest-ReventlessSeed.cmt +0 -0
  33. package/lib/bs/tests/UploadEndpointResolutionTest.ast +0 -0
  34. package/lib/bs/tests/UploadEndpointResolutionTest.res +101 -0
  35. package/lib/bs/tests/UploadEndpointResolutionTest.res.mjs +59 -0
  36. package/lib/ocaml/.compiler.log +2 -2
  37. package/lib/ocaml/ReventlessSeed.cmi +0 -0
  38. package/lib/ocaml/ReventlessSeed.cmt +0 -0
  39. package/lib/ocaml/ReventlessSeed.mlmap +1 -0
  40. package/lib/ocaml/Seed-ReventlessSeed.cmi +0 -0
  41. package/lib/ocaml/Seed-ReventlessSeed.cmt +0 -0
  42. package/lib/ocaml/Seed.ast +0 -0
  43. package/lib/ocaml/Seed.res +4 -2
  44. package/lib/ocaml/Seed_Client-ReventlessSeed.cmt +0 -0
  45. package/lib/ocaml/Seed_Connect-ReventlessSeed.cmi +0 -0
  46. package/lib/ocaml/Seed_Connect-ReventlessSeed.cmj +0 -0
  47. package/lib/ocaml/Seed_Connect-ReventlessSeed.cmt +0 -0
  48. package/lib/ocaml/Seed_Connect.ast +0 -0
  49. package/lib/ocaml/Seed_Connect.res +49 -11
  50. package/lib/ocaml/Seed_Prompt-ReventlessSeed.cmt +0 -0
  51. package/lib/ocaml/Seed_Random-ReventlessSeed.cmt +0 -0
  52. package/lib/ocaml/Seed_Runner-ReventlessSeed.cmi +0 -0
  53. package/lib/ocaml/Seed_Runner-ReventlessSeed.cmt +0 -0
  54. package/lib/ocaml/Seed_Types-ReventlessSeed.cmt +0 -0
  55. package/lib/ocaml/Seed_Upload-ReventlessSeed.cmi +0 -0
  56. package/lib/ocaml/Seed_Upload-ReventlessSeed.cmj +0 -0
  57. package/lib/ocaml/Seed_Upload-ReventlessSeed.cmt +0 -0
  58. package/lib/ocaml/Seed_Upload.ast +0 -0
  59. package/lib/ocaml/Seed_Upload.res +59 -0
  60. package/lib/ocaml/UploadEndpointResolutionTest-ReventlessSeed.cmi +0 -0
  61. package/lib/ocaml/UploadEndpointResolutionTest-ReventlessSeed.cmj +0 -0
  62. package/lib/ocaml/UploadEndpointResolutionTest-ReventlessSeed.cmt +0 -0
  63. package/lib/ocaml/UploadEndpointResolutionTest.ast +0 -0
  64. package/lib/ocaml/UploadEndpointResolutionTest.res +101 -0
  65. package/package.json +3 -2
  66. package/rescript.json +8 -1
  67. package/src/Seed.res +4 -2
  68. package/src/Seed_Connect.res +49 -11
  69. package/src/Seed_Connect.res.mjs +24 -3
  70. package/src/Seed_Upload.res +59 -0
  71. package/src/Seed_Upload.res.mjs +29 -1
  72. package/tests/UploadEndpointResolutionTest.res +101 -0
  73. package/tests/UploadEndpointResolutionTest.res.mjs +59 -0
@@ -0,0 +1,101 @@
1
+ // Which endpoint an asset uploads through once a deployment publishes one per
2
+ // declared store, and what a data set is told when none resolves.
3
+ //
4
+ // The four rows are the same ones the AutoUI renderer resolves an upload field
5
+ // by. They are pinned here because the two middle ones are what keep a
6
+ // deployment predating per-store endpoints — and the local dev server, which
7
+ // serves a single upload route — working unchanged, and because the row that
8
+ // falls back to the legacy service must never fall back to *another store*: that
9
+ // uploads into a different plugin's bucket with a 2xx and a plausible ref.
10
+
11
+ open JestGlobals
12
+
13
+ @val @scope("process") external processEnv: dict<string> = "env"
14
+
15
+ // `unresolvedReason` reads the knob, so the ambient environment has to be quiet.
16
+ let clearSkip = () => processEnv->Dict.set("SEED_SKIP_UPLOADS", "")
17
+
18
+ let perStore = Dict.fromArray([
19
+ ("Catalog.productImages", "https://catalog.example/"),
20
+ ("Ordering.invoices", "https://ordering.example/"),
21
+ ])
22
+
23
+ describe("Seed.Upload.endpointFor", () => {
24
+ testSync("a declared store with a matching endpoint uses that store's endpoint", () =>
25
+ expect(
26
+ Seed.Upload.endpointFor(
27
+ ~store="Catalog.productImages",
28
+ ~uploadEndpoint="https://legacy.example/",
29
+ ~uploadEndpoints=perStore,
30
+ ),
31
+ )->toEqual(Some("https://catalog.example/"))
32
+ )
33
+
34
+ // Not "https://ordering.example/" — a wrong guess here is a silent
35
+ // wrong-bucket write.
36
+ testSync("a declared store with no matching endpoint falls back to the legacy service", () =>
37
+ expect(
38
+ Seed.Upload.endpointFor(
39
+ ~store="Catalog.brochures",
40
+ ~uploadEndpoint="https://legacy.example/",
41
+ ~uploadEndpoints=perStore,
42
+ ),
43
+ )->toEqual(Some("https://legacy.example/"))
44
+ )
45
+
46
+ testSync("naming no store uses the legacy service", () =>
47
+ expect(
48
+ Seed.Upload.endpointFor(~uploadEndpoint="https://legacy.example/", ~uploadEndpoints=perStore),
49
+ )->toEqual(Some("https://legacy.example/"))
50
+ )
51
+
52
+ testSync("neither available resolves nothing", () =>
53
+ expect(
54
+ Seed.Upload.endpointFor(
55
+ ~store="Catalog.brochures",
56
+ ~uploadEndpoint="",
57
+ ~uploadEndpoints=Dict.make(),
58
+ ),
59
+ )->toEqual(None)
60
+ )
61
+
62
+ // The local dev server's shape: one upload route, no per-store map, and a data
63
+ // set that names its store all the same.
64
+ testSync("a single-route deployment serves a store-naming data set", () =>
65
+ expect(
66
+ Seed.Upload.endpointFor(
67
+ ~store="Catalog.productImages",
68
+ ~uploadEndpoint="http://localhost:4000/__inmemory/upload",
69
+ ~uploadEndpoints=Dict.make(),
70
+ ),
71
+ )->toEqual(Some("http://localhost:4000/__inmemory/upload"))
72
+ )
73
+ })
74
+
75
+ // "no upload endpoint" states a fact about the deployment. When the deployment
76
+ // publishes endpoints the caller could not match, the fact is about the client,
77
+ // and that phrasing sends a reader to the bucket, the presign service and the
78
+ // IAM policy — all of which are correct.
79
+ describe("Seed.Upload.unresolvedReason", () => {
80
+ beforeEach(clearSkip)
81
+
82
+ testSync("no endpoints at all reads as a fact about the deployment", () =>
83
+ expect(
84
+ Seed.Upload.unresolvedReason(~store="Catalog.productImages", ~uploadEndpoints=Dict.make()),
85
+ )->toBe("this deployment publishes no upload endpoint")
86
+ )
87
+
88
+ testSync("an unmatched store names the store and the keys that were available", () => {
89
+ let msg = Seed.Upload.unresolvedReason(~store="Catalog.brochures", ~uploadEndpoints=perStore)
90
+ expect(msg)->toContain("Catalog.brochures")
91
+ expect(msg)->toContain("Catalog.productImages")
92
+ expect(msg)->toContain("Ordering.invoices")
93
+ })
94
+
95
+ testSync("the knob outranks both, so a skipped run is never read as a broken one", () => {
96
+ processEnv->Dict.set("SEED_SKIP_UPLOADS", "1")
97
+ expect(
98
+ Seed.Upload.unresolvedReason(~store="Catalog.productImages", ~uploadEndpoints=perStore),
99
+ )->toBe("SEED_SKIP_UPLOADS is set")
100
+ })
101
+ })
@@ -0,0 +1,59 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Seed_Upload$ReventlessSeed from "../src/Seed_Upload.res.mjs";
4
+
5
+ function clearSkip() {
6
+ process.env["SEED_SKIP_UPLOADS"] = "";
7
+ }
8
+
9
+ let perStore = Object.fromEntries([
10
+ [
11
+ "Catalog.productImages",
12
+ "https://catalog.example/"
13
+ ],
14
+ [
15
+ "Ordering.invoices",
16
+ "https://ordering.example/"
17
+ ]
18
+ ]);
19
+
20
+ globalThis.describe("Seed.Upload.endpointFor", () => {
21
+ globalThis.test("a declared store with a matching endpoint uses that store's endpoint", () => {
22
+ globalThis.expect(Seed_Upload$ReventlessSeed.endpointFor("Catalog.productImages", "https://legacy.example/", perStore)).toEqual("https://catalog.example/");
23
+ });
24
+ globalThis.test("a declared store with no matching endpoint falls back to the legacy service", () => {
25
+ globalThis.expect(Seed_Upload$ReventlessSeed.endpointFor("Catalog.brochures", "https://legacy.example/", perStore)).toEqual("https://legacy.example/");
26
+ });
27
+ globalThis.test("naming no store uses the legacy service", () => {
28
+ globalThis.expect(Seed_Upload$ReventlessSeed.endpointFor(undefined, "https://legacy.example/", perStore)).toEqual("https://legacy.example/");
29
+ });
30
+ globalThis.test("neither available resolves nothing", () => {
31
+ globalThis.expect(Seed_Upload$ReventlessSeed.endpointFor("Catalog.brochures", "", {})).toEqual(undefined);
32
+ });
33
+ globalThis.test("a single-route deployment serves a store-naming data set", () => {
34
+ globalThis.expect(Seed_Upload$ReventlessSeed.endpointFor("Catalog.productImages", "http://localhost:4000/__inmemory/upload", {})).toEqual("http://localhost:4000/__inmemory/upload");
35
+ });
36
+ });
37
+
38
+ globalThis.describe("Seed.Upload.unresolvedReason", () => {
39
+ globalThis.beforeEach(clearSkip);
40
+ globalThis.test("no endpoints at all reads as a fact about the deployment", () => {
41
+ globalThis.expect(Seed_Upload$ReventlessSeed.unresolvedReason("Catalog.productImages", {})).toBe("this deployment publishes no upload endpoint");
42
+ });
43
+ globalThis.test("an unmatched store names the store and the keys that were available", () => {
44
+ let msg = Seed_Upload$ReventlessSeed.unresolvedReason("Catalog.brochures", perStore);
45
+ globalThis.expect(msg).toContain("Catalog.brochures");
46
+ globalThis.expect(msg).toContain("Catalog.productImages");
47
+ globalThis.expect(msg).toContain("Ordering.invoices");
48
+ });
49
+ globalThis.test("the knob outranks both, so a skipped run is never read as a broken one", () => {
50
+ process.env["SEED_SKIP_UPLOADS"] = "1";
51
+ globalThis.expect(Seed_Upload$ReventlessSeed.unresolvedReason("Catalog.productImages", perStore)).toBe("SEED_SKIP_UPLOADS is set");
52
+ });
53
+ });
54
+
55
+ export {
56
+ clearSkip,
57
+ perStore,
58
+ }
59
+ /* perStore Not a pure module */