@reventlessdev/reventless-aws 3.0.0-alpha.252 → 3.0.0-alpha.254

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 (38) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/package.json +8 -8
  3. package/src/Platform.res +159 -21
  4. package/src/Platform.res.mjs +120 -8
  5. package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res +5 -0
  6. package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res.mjs +3 -0
  7. package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res +5 -0
  8. package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res.mjs +3 -0
  9. package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +66 -8
  10. package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs +16 -3
  11. package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res +5 -0
  12. package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res.mjs +3 -0
  13. package/src/adapter/Task/TaskBucket_S3.res +11 -0
  14. package/src/adapter/Task/TaskBucket_S3.res.mjs +3 -0
  15. package/src/adapter/Upload/Upload_Claim_S3.res +361 -0
  16. package/src/adapter/Upload/Upload_Claim_S3.res.mjs +203 -0
  17. package/src/adapter/Upload/Upload_Claim_S3_Ops.res +279 -0
  18. package/src/adapter/Upload/Upload_Claim_S3_Ops.res.mjs +261 -0
  19. package/src/adapter/Upload/Upload_PendingTag.res +41 -0
  20. package/src/adapter/Upload/Upload_PendingTag.res.mjs +15 -0
  21. package/src/adapter/Upload/Upload_Presign_S3.res +12 -2
  22. package/src/adapter/Upload/Upload_Presign_S3.res.mjs +1 -0
  23. package/src/adapter/Upload/Upload_Presign_S3_Ops.res +17 -1
  24. package/src/adapter/Upload/Upload_Presign_S3_Ops.res.mjs +3 -1
  25. package/src/capability/Capability_ObjectStore_S3.res +42 -1
  26. package/src/capability/Capability_ObjectStore_S3.res.mjs +19 -1
  27. package/src/components/Api/AppSync_Adapter.res +36 -0
  28. package/src/components/Api/AppSync_Adapter.res.mjs +14 -0
  29. package/src/util/Util_LogRetention.res +86 -0
  30. package/src/util/Util_LogRetention.res.mjs +43 -0
  31. package/src/util/Util_StoreLayout.res +62 -9
  32. package/src/util/Util_StoreLayout.res.mjs +20 -2
  33. package/tests/Upload_ClaimTest.res +132 -0
  34. package/tests/Upload_ClaimTest.res.mjs +101 -0
  35. package/tests/Util_LogRetentionTest.res +122 -0
  36. package/tests/Util_LogRetentionTest.res.mjs +95 -0
  37. package/tests/Util_StoreLayoutTest.res +79 -3
  38. package/tests/Util_StoreLayoutTest.res.mjs +47 -2
@@ -0,0 +1,95 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Util_HostUiDomain$ReventlessAws from "../src/util/Util_HostUiDomain.res.mjs";
4
+ import * as Util_LogRetention$ReventlessAws from "../src/util/Util_LogRetention.res.mjs";
5
+
6
+ globalThis.describe("Util_LogRetention.retentionDaysFor", () => {
7
+ globalThis.test("prod keeps logs a year", () => {
8
+ globalThis.expect(Util_LogRetention$ReventlessAws.retentionDaysFor("prod", Util_HostUiDomain$ReventlessAws.defaultProdStacks, undefined)).toBe(365);
9
+ });
10
+ globalThis.test("'main' is production too, by the shared prod list", () => {
11
+ globalThis.expect(Util_LogRetention$ReventlessAws.retentionDaysFor("main", Util_HostUiDomain$ReventlessAws.defaultProdStacks, undefined)).toBe(365);
12
+ });
13
+ globalThis.test("beta keeps a month of pre-prod history", () => {
14
+ globalThis.expect(Util_LogRetention$ReventlessAws.retentionDaysFor("beta", Util_HostUiDomain$ReventlessAws.defaultProdStacks, undefined)).toBe(30);
15
+ });
16
+ globalThis.test("a PR stack keeps the minimum — torn down quickly", () => {
17
+ globalThis.expect(Util_LogRetention$ReventlessAws.retentionDaysFor("pr-1234", Util_HostUiDomain$ReventlessAws.defaultProdStacks, undefined)).toBe(3);
18
+ });
19
+ globalThis.test("alpha keeps a week — active development, consumed within hours", () => {
20
+ globalThis.expect(Util_LogRetention$ReventlessAws.retentionDaysFor("alpha", Util_HostUiDomain$ReventlessAws.defaultProdStacks, undefined)).toBe(7);
21
+ });
22
+ globalThis.test("an unlisted stack falls open to the dev tier", () => {
23
+ globalThis.expect(Util_LogRetention$ReventlessAws.retentionDaysFor("production", Util_HostUiDomain$ReventlessAws.defaultProdStacks, undefined)).toBe(7);
24
+ });
25
+ globalThis.test("adding it to the prod list is the fix", () => {
26
+ globalThis.expect(Util_LogRetention$ReventlessAws.retentionDaysFor("production", [
27
+ "prod",
28
+ "production"
29
+ ], undefined)).toBe(365);
30
+ });
31
+ globalThis.test("a config override wins over the tier default", () => {
32
+ globalThis.expect(Util_LogRetention$ReventlessAws.retentionDaysFor("alpha", Util_HostUiDomain$ReventlessAws.defaultProdStacks, 14)).toBe(14);
33
+ });
34
+ globalThis.test("0 = never expire is expressible via the override", () => {
35
+ globalThis.expect(Util_LogRetention$ReventlessAws.retentionDaysFor("prod", Util_HostUiDomain$ReventlessAws.defaultProdStacks, 0)).toBe(0);
36
+ });
37
+ });
38
+
39
+ globalThis.describe("Util_LogRetention.logLevelFor", () => {
40
+ globalThis.test("prod is quiet — info, no debug noise or payload leakage", () => {
41
+ globalThis.expect(Util_LogRetention$ReventlessAws.logLevelFor("prod", Util_HostUiDomain$ReventlessAws.defaultProdStacks, undefined)).toBe("info");
42
+ });
43
+ globalThis.test("beta mirrors prod so pre-prod behaves like prod", () => {
44
+ globalThis.expect(Util_LogRetention$ReventlessAws.logLevelFor("beta", Util_HostUiDomain$ReventlessAws.defaultProdStacks, undefined)).toBe("info");
45
+ });
46
+ globalThis.test("alpha is verbose — debug feedback during active development", () => {
47
+ globalThis.expect(Util_LogRetention$ReventlessAws.logLevelFor("alpha", Util_HostUiDomain$ReventlessAws.defaultProdStacks, undefined)).toBe("debug");
48
+ });
49
+ globalThis.test("a PR stack is verbose too", () => {
50
+ globalThis.expect(Util_LogRetention$ReventlessAws.logLevelFor("pr-7", Util_HostUiDomain$ReventlessAws.defaultProdStacks, undefined)).toBe("debug");
51
+ });
52
+ globalThis.test("a config override wins over the tier default", () => {
53
+ globalThis.expect(Util_LogRetention$ReventlessAws.logLevelFor("prod", Util_HostUiDomain$ReventlessAws.defaultProdStacks, "debug")).toBe("debug");
54
+ });
55
+ });
56
+
57
+ globalThis.describe("Util_LogRetention.managesLogGroup", () => {
58
+ globalThis.test("alpha is managed", () => {
59
+ globalThis.expect(Util_LogRetention$ReventlessAws.managesLogGroup("alpha", undefined)).toBe(true);
60
+ });
61
+ globalThis.test("a PR stack is managed", () => {
62
+ globalThis.expect(Util_LogRetention$ReventlessAws.managesLogGroup("pr-42", undefined)).toBe(true);
63
+ });
64
+ globalThis.test("prod is managed too — a fresh prod stack has no group to adopt", () => {
65
+ globalThis.expect(Util_LogRetention$ReventlessAws.managesLogGroup("prod", undefined)).toBe(true);
66
+ });
67
+ globalThis.test("beta is managed too", () => {
68
+ globalThis.expect(Util_LogRetention$ReventlessAws.managesLogGroup("beta", undefined)).toBe(true);
69
+ });
70
+ globalThis.test("a stack named in unmanagedLogGroupStacks is left auto-created", () => {
71
+ globalThis.expect(Util_LogRetention$ReventlessAws.managesLogGroup("legacy-prod", ["legacy-prod"])).toBe(false);
72
+ });
73
+ globalThis.test("only the named stacks are excluded — others stay managed", () => {
74
+ globalThis.expect(Util_LogRetention$ReventlessAws.managesLogGroup("alpha", ["legacy-prod"])).toBe(true);
75
+ });
76
+ });
77
+
78
+ globalThis.describe("Util_LogRetention.parseUnmanagedStacks", () => {
79
+ globalThis.test("empty config manages every stack", () => {
80
+ globalThis.expect(Util_LogRetention$ReventlessAws.parseUnmanagedStacks("")).toEqual([]);
81
+ });
82
+ globalThis.test("CSV is trimmed and empty entries dropped", () => {
83
+ globalThis.expect(Util_LogRetention$ReventlessAws.parseUnmanagedStacks(" legacy-prod , , old-beta ")).toEqual([
84
+ "legacy-prod",
85
+ "old-beta"
86
+ ]);
87
+ });
88
+ });
89
+
90
+ let prodStacks = Util_HostUiDomain$ReventlessAws.defaultProdStacks;
91
+
92
+ export {
93
+ prodStacks,
94
+ }
95
+ /* Not a pure module */
@@ -222,8 +222,84 @@ describe("Util_StoreLayout.bucketNameFor", () => {
222
222
  describe("Util_StoreLayout.keyPrefixFor", () => {
223
223
  // The assertion the whole dual-layout scheme rests on: a ref is
224
224
  // layout-independent, so the same declaration produces the same stored string
225
- // on a per-store stack and a shared one.
226
- testSync("the key prefix is the store name in both layouts", () =>
227
- expect(Util_StoreLayout.keyPrefixFor(~store="productImages"))->toBe("productImages")
225
+ // on a per-store stack and a shared one. Plugin and store are both
226
+ // stack-invariant, so qualifying by plugin keeps that property.
227
+ testSync("the key prefix qualifies the store with its plugin", () =>
228
+ expect(Util_StoreLayout.keyPrefixFor(~plugin="Catalog", ~store="productImages"))->toBe(
229
+ "Catalog/productImages",
230
+ )
231
+ )
232
+
233
+ // The reason it is qualified: the prefix is a platform-global namespace (one
234
+ // distribution, one cache behavior per prefix), so two plugins declaring one
235
+ // store name were unroutable in EITHER layout until the plugin qualified them.
236
+ testSync("two plugins declaring one store name get distinct prefixes", () =>
237
+ expect(
238
+ Util_StoreLayout.keyPrefixFor(~plugin="Catalog", ~store="productImages") !=
239
+ Util_StoreLayout.keyPrefixFor(~plugin="Ordering", ~store="productImages"),
240
+ )->toBe(true)
241
+ )
242
+ })
243
+
244
+ describe("Util_StoreLayout.pendingExpiryFor", () => {
245
+ // The default is the whole point: expiry is the one step in the mechanism that
246
+ // deletes objects, and it is only sound once reconciliation has confirmed the
247
+ // tagged set is the unreferenced set. A store nobody named accumulates.
248
+ testSync("no config at all means no store expires anything", () =>
249
+ expect(
250
+ Util_StoreLayout.pendingExpiryFor(~config=None, ~store="Catalog.productImages"),
251
+ )->toEqual(None)
252
+ )
253
+
254
+ testSync("a store the config does not name expires nothing", () =>
255
+ expect(
256
+ Util_StoreLayout.pendingExpiryFor(
257
+ ~config=Some("Ordering.receipts=14"),
258
+ ~store="Catalog.productImages",
259
+ ),
260
+ )->toEqual(None)
261
+ )
262
+
263
+ testSync("a named store takes its own retention", () =>
264
+ expect(
265
+ Util_StoreLayout.pendingExpiryFor(
266
+ ~config=Some("Catalog.productImages=30"),
267
+ ~store="Catalog.productImages",
268
+ ),
269
+ )->toEqual(Some(30))
270
+ )
271
+
272
+ // Per store, one at a time — the plan's sequencing expressed in the setting.
273
+ testSync("stores are enabled independently, with their own values", () => {
274
+ let config = Some("Catalog.productImages=30, Ordering.receipts=14")
275
+ expect((
276
+ Util_StoreLayout.pendingExpiryFor(~config, ~store="Catalog.productImages"),
277
+ Util_StoreLayout.pendingExpiryFor(~config, ~store="Ordering.receipts"),
278
+ Util_StoreLayout.pendingExpiryFor(~config, ~store="Catalog.other"),
279
+ ))->toEqual((Some(30), Some(14), None))
280
+ })
281
+
282
+ // Guessing at what a typo meant, in the one setting that deletes objects, is
283
+ // not a service — an unreadable entry leaves the store accumulating.
284
+ testSync("a malformed or non-positive entry is ignored, not defaulted", () => {
285
+ let of_ = c => Util_StoreLayout.pendingExpiryFor(~config=Some(c), ~store="Catalog.productImages")
286
+ expect((
287
+ of_("Catalog.productImages"),
288
+ of_("Catalog.productImages="),
289
+ of_("Catalog.productImages=soon"),
290
+ of_("Catalog.productImages=0"),
291
+ of_("Catalog.productImages=-1"),
292
+ ))->toEqual((None, None, None, None, None))
293
+ })
294
+
295
+ // The prefix is a platform-global namespace, so two plugins' stores are
296
+ // distinct keys — enabling one must not enable the other.
297
+ testSync("a store name is matched whole, not by prefix", () =>
298
+ expect(
299
+ Util_StoreLayout.pendingExpiryFor(
300
+ ~config=Some("Catalog.productImages=30"),
301
+ ~store="Catalog.productImagesArchive",
302
+ ),
303
+ )->toEqual(None)
228
304
  )
229
305
  })
@@ -113,8 +113,53 @@ globalThis.describe("Util_StoreLayout.bucketNameFor", () => {
113
113
  });
114
114
 
115
115
  globalThis.describe("Util_StoreLayout.keyPrefixFor", () => {
116
- globalThis.test("the key prefix is the store name in both layouts", () => {
117
- globalThis.expect(Util_StoreLayout$ReventlessAws.keyPrefixFor("productImages")).toBe("productImages");
116
+ globalThis.test("the key prefix qualifies the store with its plugin", () => {
117
+ globalThis.expect(Util_StoreLayout$ReventlessAws.keyPrefixFor("Catalog", "productImages")).toBe("Catalog/productImages");
118
+ });
119
+ globalThis.test("two plugins declaring one store name get distinct prefixes", () => {
120
+ globalThis.expect(Util_StoreLayout$ReventlessAws.keyPrefixFor("Catalog", "productImages") !== Util_StoreLayout$ReventlessAws.keyPrefixFor("Ordering", "productImages")).toBe(true);
121
+ });
122
+ });
123
+
124
+ globalThis.describe("Util_StoreLayout.pendingExpiryFor", () => {
125
+ globalThis.test("no config at all means no store expires anything", () => {
126
+ globalThis.expect(Util_StoreLayout$ReventlessAws.pendingExpiryFor(undefined, "Catalog.productImages")).toEqual(undefined);
127
+ });
128
+ globalThis.test("a store the config does not name expires nothing", () => {
129
+ globalThis.expect(Util_StoreLayout$ReventlessAws.pendingExpiryFor("Ordering.receipts=14", "Catalog.productImages")).toEqual(undefined);
130
+ });
131
+ globalThis.test("a named store takes its own retention", () => {
132
+ globalThis.expect(Util_StoreLayout$ReventlessAws.pendingExpiryFor("Catalog.productImages=30", "Catalog.productImages")).toEqual(30);
133
+ });
134
+ globalThis.test("stores are enabled independently, with their own values", () => {
135
+ let config = "Catalog.productImages=30, Ordering.receipts=14";
136
+ globalThis.expect([
137
+ Util_StoreLayout$ReventlessAws.pendingExpiryFor(config, "Catalog.productImages"),
138
+ Util_StoreLayout$ReventlessAws.pendingExpiryFor(config, "Ordering.receipts"),
139
+ Util_StoreLayout$ReventlessAws.pendingExpiryFor(config, "Catalog.other")
140
+ ]).toEqual([
141
+ 30,
142
+ 14,
143
+ undefined
144
+ ]);
145
+ });
146
+ globalThis.test("a malformed or non-positive entry is ignored, not defaulted", () => {
147
+ globalThis.expect([
148
+ Util_StoreLayout$ReventlessAws.pendingExpiryFor("Catalog.productImages", "Catalog.productImages"),
149
+ Util_StoreLayout$ReventlessAws.pendingExpiryFor("Catalog.productImages=", "Catalog.productImages"),
150
+ Util_StoreLayout$ReventlessAws.pendingExpiryFor("Catalog.productImages=soon", "Catalog.productImages"),
151
+ Util_StoreLayout$ReventlessAws.pendingExpiryFor("Catalog.productImages=0", "Catalog.productImages"),
152
+ Util_StoreLayout$ReventlessAws.pendingExpiryFor("Catalog.productImages=-1", "Catalog.productImages")
153
+ ]).toEqual([
154
+ undefined,
155
+ undefined,
156
+ undefined,
157
+ undefined,
158
+ undefined
159
+ ]);
160
+ });
161
+ globalThis.test("a store name is matched whole, not by prefix", () => {
162
+ globalThis.expect(Util_StoreLayout$ReventlessAws.pendingExpiryFor("Catalog.productImages=30", "Catalog.productImagesArchive")).toEqual(undefined);
118
163
  });
119
164
  });
120
165