@reventlessdev/reventless-postgres 3.0.0-alpha.1 → 3.0.0-alpha.100

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 (167) hide show
  1. package/CHANGELOG.md +792 -0
  2. package/README.md +83 -0
  3. package/lib/bs/.compiler.log +2 -2
  4. package/lib/bs/ReventlessPostgres.cmi +0 -0
  5. package/lib/bs/ReventlessPostgres.cmt +0 -0
  6. package/lib/bs/ReventlessPostgres.mlmap +4 -1
  7. package/lib/bs/compiler-info.json +2 -2
  8. package/lib/bs/src/DcbEventLogStorage_Postgres-ReventlessPostgres.cmi +0 -0
  9. package/lib/bs/src/DcbEventLogStorage_Postgres-ReventlessPostgres.cmj +0 -0
  10. package/lib/bs/src/DcbEventLogStorage_Postgres-ReventlessPostgres.cmt +0 -0
  11. package/lib/bs/src/DcbEventLogStorage_Postgres.ast +0 -0
  12. package/lib/bs/src/DcbEventLogStorage_Postgres.res +25 -340
  13. package/lib/bs/src/DcbEventLogStorage_Postgres.res.mjs +32 -348
  14. package/lib/bs/src/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
  15. package/lib/bs/src/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
  16. package/lib/bs/src/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
  17. package/lib/bs/src/DcbEventLogStorage_Postgres_Ops.ast +0 -0
  18. package/lib/bs/src/DcbEventLogStorage_Postgres_Ops.res +350 -0
  19. package/lib/bs/src/DcbEventLogStorage_Postgres_Ops.res.mjs +380 -0
  20. package/lib/bs/src/EventLogChangeFeed-ReventlessPostgres.cmi +0 -0
  21. package/lib/bs/src/EventLogChangeFeed-ReventlessPostgres.cmj +0 -0
  22. package/lib/bs/src/EventLogChangeFeed-ReventlessPostgres.cmt +0 -0
  23. package/lib/bs/src/EventLogChangeFeed.ast +0 -0
  24. package/lib/bs/src/EventLogChangeFeed.res +187 -0
  25. package/lib/bs/src/EventLogChangeFeed.res.mjs +134 -0
  26. package/lib/bs/src/EventLogStorage_Postgres-ReventlessPostgres.cmi +0 -0
  27. package/lib/bs/src/EventLogStorage_Postgres-ReventlessPostgres.cmj +0 -0
  28. package/lib/bs/src/EventLogStorage_Postgres-ReventlessPostgres.cmt +0 -0
  29. package/lib/bs/src/EventLogStorage_Postgres.ast +0 -0
  30. package/lib/bs/src/EventLogStorage_Postgres.res +12 -170
  31. package/lib/bs/src/EventLogStorage_Postgres.res.mjs +20 -186
  32. package/lib/bs/src/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
  33. package/lib/bs/src/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
  34. package/lib/bs/src/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
  35. package/lib/bs/src/EventLogStorage_Postgres_Ops.ast +0 -0
  36. package/lib/bs/src/EventLogStorage_Postgres_Ops.res +180 -0
  37. package/lib/bs/src/EventLogStorage_Postgres_Ops.res.mjs +202 -0
  38. package/lib/bs/src/PgChangeFeed-ReventlessPostgres.cmi +0 -0
  39. package/lib/bs/src/PgChangeFeed-ReventlessPostgres.cmt +0 -0
  40. package/lib/bs/src/PgChangeFeed.ast +0 -0
  41. package/lib/bs/src/PgChangeFeed.res +6 -1
  42. package/lib/bs/src/PgChangeFeed.res.mjs +6 -6
  43. package/lib/bs/src/PgDriver-ReventlessPostgres.cmi +0 -0
  44. package/lib/bs/src/PgDriver-ReventlessPostgres.cmt +0 -0
  45. package/lib/bs/src/PgDriver-ReventlessPostgres.cmti +0 -0
  46. package/lib/bs/src/PgDriver.ast +0 -0
  47. package/lib/bs/src/PgDriver.iast +0 -0
  48. package/lib/bs/src/PgSchema-ReventlessPostgres.cmi +0 -0
  49. package/lib/bs/src/PgSchema-ReventlessPostgres.cmt +0 -0
  50. package/lib/bs/src/PgSchema.ast +0 -0
  51. package/lib/bs/src/PgSchema.res +36 -2
  52. package/lib/bs/src/PgSchema.res.mjs +9 -2
  53. package/lib/bs/src/QueryDbStorage_Postgres-ReventlessPostgres.cmi +0 -0
  54. package/lib/bs/src/QueryDbStorage_Postgres-ReventlessPostgres.cmj +0 -0
  55. package/lib/bs/src/QueryDbStorage_Postgres-ReventlessPostgres.cmt +0 -0
  56. package/lib/bs/src/QueryDbStorage_Postgres.ast +0 -0
  57. package/lib/bs/src/QueryDbStorage_Postgres.res +11 -213
  58. package/lib/bs/src/QueryDbStorage_Postgres.res.mjs +27 -191
  59. package/lib/bs/src/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
  60. package/lib/bs/src/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
  61. package/lib/bs/src/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
  62. package/lib/bs/src/QueryDbStorage_Postgres_Ops.ast +0 -0
  63. package/lib/bs/src/QueryDbStorage_Postgres_Ops.res +229 -0
  64. package/lib/bs/src/QueryDbStorage_Postgres_Ops.res.mjs +222 -0
  65. package/lib/bs/src/QueryEnginePostgres-ReventlessPostgres.cmi +0 -0
  66. package/lib/bs/src/QueryEnginePostgres-ReventlessPostgres.cmt +0 -0
  67. package/lib/bs/src/QueryEnginePostgres.ast +0 -0
  68. package/lib/bs/src/QueryEnginePostgres.res +280 -7
  69. package/lib/bs/src/QueryEnginePostgres.res.mjs +180 -15
  70. package/lib/bs/tests/PostgresIntegrationTest-ReventlessPostgres.cmi +0 -0
  71. package/lib/bs/tests/PostgresIntegrationTest-ReventlessPostgres.cmt +0 -0
  72. package/lib/bs/tests/PostgresIntegrationTest.ast +0 -0
  73. package/lib/bs/tests/PostgresIntegrationTest.res +68 -0
  74. package/lib/bs/tests/PostgresIntegrationTest.res.mjs +49 -0
  75. package/lib/bs/tests/QueryEnginePostgresListPageTest-ReventlessPostgres.cmi +0 -0
  76. package/lib/bs/tests/QueryEnginePostgresListPageTest-ReventlessPostgres.cmj +0 -0
  77. package/lib/bs/tests/QueryEnginePostgresListPageTest-ReventlessPostgres.cmt +0 -0
  78. package/lib/bs/tests/QueryEnginePostgresListPageTest.ast +0 -0
  79. package/lib/bs/tests/QueryEnginePostgresListPageTest.res +312 -0
  80. package/lib/bs/tests/QueryEnginePostgresListPageTest.res.mjs +461 -0
  81. package/lib/ocaml/.compiler.log +2 -2
  82. package/lib/ocaml/DcbEventLogStorage_Postgres-ReventlessPostgres.cmi +0 -0
  83. package/lib/ocaml/DcbEventLogStorage_Postgres-ReventlessPostgres.cmj +0 -0
  84. package/lib/ocaml/DcbEventLogStorage_Postgres-ReventlessPostgres.cmt +0 -0
  85. package/lib/ocaml/DcbEventLogStorage_Postgres.ast +0 -0
  86. package/lib/ocaml/DcbEventLogStorage_Postgres.res +25 -340
  87. package/lib/ocaml/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
  88. package/lib/ocaml/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
  89. package/lib/ocaml/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
  90. package/lib/ocaml/DcbEventLogStorage_Postgres_Ops.ast +0 -0
  91. package/lib/ocaml/DcbEventLogStorage_Postgres_Ops.res +350 -0
  92. package/lib/ocaml/EventLogChangeFeed-ReventlessPostgres.cmi +0 -0
  93. package/lib/ocaml/EventLogChangeFeed-ReventlessPostgres.cmj +0 -0
  94. package/lib/ocaml/EventLogChangeFeed-ReventlessPostgres.cmt +0 -0
  95. package/lib/ocaml/EventLogChangeFeed.ast +0 -0
  96. package/lib/ocaml/EventLogChangeFeed.res +187 -0
  97. package/lib/ocaml/EventLogStorage_Postgres-ReventlessPostgres.cmi +0 -0
  98. package/lib/ocaml/EventLogStorage_Postgres-ReventlessPostgres.cmj +0 -0
  99. package/lib/ocaml/EventLogStorage_Postgres-ReventlessPostgres.cmt +0 -0
  100. package/lib/ocaml/EventLogStorage_Postgres.ast +0 -0
  101. package/lib/ocaml/EventLogStorage_Postgres.res +12 -170
  102. package/lib/ocaml/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
  103. package/lib/ocaml/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
  104. package/lib/ocaml/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
  105. package/lib/ocaml/EventLogStorage_Postgres_Ops.ast +0 -0
  106. package/lib/ocaml/EventLogStorage_Postgres_Ops.res +180 -0
  107. package/lib/ocaml/PgChangeFeed-ReventlessPostgres.cmi +0 -0
  108. package/lib/ocaml/PgChangeFeed-ReventlessPostgres.cmt +0 -0
  109. package/lib/ocaml/PgChangeFeed.ast +0 -0
  110. package/lib/ocaml/PgChangeFeed.res +6 -1
  111. package/lib/ocaml/PgDriver-ReventlessPostgres.cmi +0 -0
  112. package/lib/ocaml/PgDriver-ReventlessPostgres.cmt +0 -0
  113. package/lib/ocaml/PgDriver-ReventlessPostgres.cmti +0 -0
  114. package/lib/ocaml/PgDriver.ast +0 -0
  115. package/lib/ocaml/PgDriver.iast +0 -0
  116. package/lib/ocaml/PgSchema-ReventlessPostgres.cmi +0 -0
  117. package/lib/ocaml/PgSchema-ReventlessPostgres.cmt +0 -0
  118. package/lib/ocaml/PgSchema.ast +0 -0
  119. package/lib/ocaml/PgSchema.res +36 -2
  120. package/lib/ocaml/PostgresIntegrationTest.res +68 -0
  121. package/lib/ocaml/QueryDbStorage_Postgres-ReventlessPostgres.cmi +0 -0
  122. package/lib/ocaml/QueryDbStorage_Postgres-ReventlessPostgres.cmj +0 -0
  123. package/lib/ocaml/QueryDbStorage_Postgres-ReventlessPostgres.cmt +0 -0
  124. package/lib/ocaml/QueryDbStorage_Postgres.ast +0 -0
  125. package/lib/ocaml/QueryDbStorage_Postgres.res +11 -213
  126. package/lib/ocaml/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
  127. package/lib/ocaml/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
  128. package/lib/ocaml/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
  129. package/lib/ocaml/QueryDbStorage_Postgres_Ops.ast +0 -0
  130. package/lib/ocaml/QueryDbStorage_Postgres_Ops.res +229 -0
  131. package/lib/ocaml/QueryEnginePostgres-ReventlessPostgres.cmi +0 -0
  132. package/lib/ocaml/QueryEnginePostgres-ReventlessPostgres.cmt +0 -0
  133. package/lib/ocaml/QueryEnginePostgres.ast +0 -0
  134. package/lib/ocaml/QueryEnginePostgres.res +280 -7
  135. package/lib/ocaml/QueryEnginePostgresListPageTest.res +312 -0
  136. package/lib/ocaml/ReventlessPostgres.cmi +0 -0
  137. package/lib/ocaml/ReventlessPostgres.cmt +0 -0
  138. package/lib/ocaml/ReventlessPostgres.mlmap +5 -0
  139. package/package.json +12 -12
  140. package/rescript.json +2 -1
  141. package/src/DcbEventLogStorage_Postgres.res +25 -340
  142. package/src/DcbEventLogStorage_Postgres.res.mjs +32 -348
  143. package/src/DcbEventLogStorage_Postgres_Ops.res +350 -0
  144. package/src/DcbEventLogStorage_Postgres_Ops.res.mjs +380 -0
  145. package/src/EventLogChangeFeed.res +187 -0
  146. package/src/EventLogChangeFeed.res.mjs +134 -0
  147. package/src/EventLogStorage_Postgres.res +12 -170
  148. package/src/EventLogStorage_Postgres.res.mjs +20 -186
  149. package/src/EventLogStorage_Postgres_Ops.res +180 -0
  150. package/src/EventLogStorage_Postgres_Ops.res.mjs +202 -0
  151. package/src/PgChangeFeed.res +6 -1
  152. package/src/PgChangeFeed.res.mjs +6 -6
  153. package/src/PgSchema.res +36 -2
  154. package/src/PgSchema.res.mjs +9 -2
  155. package/src/QueryDbStorage_Postgres.res +11 -213
  156. package/src/QueryDbStorage_Postgres.res.mjs +27 -191
  157. package/src/QueryDbStorage_Postgres_Ops.res +229 -0
  158. package/src/QueryDbStorage_Postgres_Ops.res.mjs +222 -0
  159. package/src/QueryEnginePostgres.res +280 -7
  160. package/src/QueryEnginePostgres.res.mjs +180 -15
  161. package/tests/PostgresIntegrationTest.res +68 -0
  162. package/tests/QueryEnginePostgresListPageTest.res +312 -0
  163. package/lib/ocaml/PostgresIntegrationTest-ReventlessPostgres.cmi +0 -0
  164. package/lib/ocaml/PostgresIntegrationTest-ReventlessPostgres.cmj +0 -0
  165. package/lib/ocaml/PostgresIntegrationTest-ReventlessPostgres.cmt +0 -0
  166. package/lib/ocaml/PostgresIntegrationTest.ast +0 -0
  167. package/tests/PostgresIntegrationTest.res.mjs +0 -328
@@ -1,9 +1,11 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
3
4
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
- import * as Pulumi from "@pulumi/pulumi";
5
+ import * as Stdlib_Nullable from "@rescript/runtime/lib/es6/Stdlib_Nullable.js";
5
6
  import * as PgDriver$ReventlessPostgres from "./PgDriver.res.mjs";
6
- import * as QueryDbStorage_Postgres$ReventlessPostgres from "./QueryDbStorage_Postgres.res.mjs";
7
+ import * as QueryDbListQuery$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/QueryDbListQuery.res.mjs";
8
+ import * as QueryDbStorage_Postgres_Ops$ReventlessPostgres from "./QueryDbStorage_Postgres_Ops.res.mjs";
7
9
 
8
10
  function valueToText(v) {
9
11
  switch (v.TAG) {
@@ -102,25 +104,25 @@ function subIdSql(b, field, cmp, v) {
102
104
  }
103
105
 
104
106
  function decodeRow(withId, row) {
105
- let item = QueryDbStorage_Postgres$ReventlessPostgres.decodeItem(row);
107
+ let item = QueryDbStorage_Postgres_Ops$ReventlessPostgres.decodeItem(row);
106
108
  if (!withId) {
107
109
  return item;
108
110
  }
109
111
  let match = row["partition_key"];
110
112
  let pk = typeof match === "string" ? match : "";
111
- return QueryDbStorage_Postgres$ReventlessPostgres.withId(item, pk);
113
+ return QueryDbStorage_Postgres_Ops$ReventlessPostgres.withId(item, pk);
112
114
  }
113
115
 
114
116
  function Make(P) {
115
117
  let query = async (readModelName, key, id, subIdConfig, filterConfigs, ascending, limit) => {
116
- let table = QueryDbStorage_Postgres$ReventlessPostgres.tableName(readModelName);
118
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
117
119
  let keyStr = key !== undefined ? key : valueToText(id);
118
120
  let b = {
119
121
  params: []
120
122
  };
121
123
  let where = [
122
124
  `partition_key = ` + param(b, keyStr),
123
- QueryDbStorage_Postgres$ReventlessPostgres.notExpiredClause
125
+ QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause
124
126
  ];
125
127
  if (subIdConfig !== undefined) {
126
128
  where.push(subIdSql(b, subIdConfig[0], subIdConfig[1], subIdConfig[2]));
@@ -134,29 +136,192 @@ function Make(P) {
134
136
  return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(false, extra));
135
137
  };
136
138
  let scan = async (readModelName, filterConfigs, limit) => {
137
- let table = QueryDbStorage_Postgres$ReventlessPostgres.tableName(readModelName);
139
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
138
140
  let b = {
139
141
  params: []
140
142
  };
141
- let where = [QueryDbStorage_Postgres$ReventlessPostgres.notExpiredClause];
143
+ let where = [QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause];
142
144
  filterConfigs.forEach(param => {
143
145
  where.push(filterSql(b, param[0], param[1], param[2]));
144
146
  });
145
147
  let sql = `SELECT partition_key, item FROM ` + table + ` WHERE ` + where.join(" AND ") + ` ORDER BY partition_key, sub_key LIMIT ` + param(b, limit);
146
148
  return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(true, extra));
147
149
  };
148
- let make = _allQueryDbs => Pulumi.output({
149
- scan: scan,
150
- query: query
151
- });
150
+ let indexLookup = async (readModelName, field, value) => {
151
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
152
+ let b = {
153
+ params: []
154
+ };
155
+ let sql = `SELECT partition_key, item FROM ` + table + ` WHERE ` + col(field) + ` = ` + param(b, value) + ` AND ` + QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause;
156
+ return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(true, extra));
157
+ };
158
+ let byIds = async (readModelName, ids) => {
159
+ if (ids.length === 0) {
160
+ return [];
161
+ }
162
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
163
+ let b = {
164
+ params: []
165
+ };
166
+ let idsJson = ids.map(prim => prim);
167
+ let sql = `SELECT partition_key, item FROM ` + table + ` WHERE partition_key = ANY(` + param(b, idsJson) + `::text[]) AND ` + QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause;
168
+ return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(true, extra));
169
+ };
170
+ let idExprC = `COALESCE(item->>'id', partition_key) COLLATE "C"`;
171
+ let jsonTextC = field => col(field) + ` COLLATE "C"`;
172
+ let listPage = async (readModelName, argsDict, capability, param$1, ownerScope) => {
173
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
174
+ let filterDict = Stdlib_Option.getOr(Stdlib_Option.flatMap(argsDict["filter"], Stdlib_JSON.Decode.object), {});
175
+ let strNonEmpty = k => Stdlib_Option.mapOr(Stdlib_Option.flatMap(filterDict[k], Stdlib_JSON.Decode.string), false, s => s.length > 0);
176
+ let hasIds = Stdlib_Option.mapOr(Stdlib_Option.flatMap(filterDict["ids"], Stdlib_JSON.Decode.array), false, a => a.length !== 0);
177
+ let last = Stdlib_Option.flatMap(argsDict["last"], Stdlib_JSON.Decode.float);
178
+ let before = Stdlib_Option.flatMap(argsDict["before"], Stdlib_JSON.Decode.string);
179
+ if (strNonEmpty("search") || strNonEmpty("searchPrefix") || hasIds || Stdlib_Option.isSome(last) || Stdlib_Option.isSome(before)) {
180
+ return;
181
+ }
182
+ let b = {
183
+ params: []
184
+ };
185
+ let whereParts = [QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause];
186
+ if (ownerScope !== undefined) {
187
+ whereParts.push(jsonTextC(ownerScope[0]) + ` = ` + param(b, ownerScope[1]));
188
+ }
189
+ let valString = v => {
190
+ let s = Stdlib_JSON.Decode.string(v);
191
+ if (s !== undefined) {
192
+ return s;
193
+ } else {
194
+ return Stdlib_Option.map(Stdlib_JSON.Decode.float(v), f => f.toString());
195
+ }
196
+ };
197
+ capability.filterFields.forEach(f => {
198
+ let v = filterDict[f.name + "Eq"];
199
+ if (v !== undefined && v !== null) {
200
+ whereParts.push(jsonTextC(f.name) + ` = ` + param(b, Stdlib_Option.getOr(valString(v), "")));
201
+ }
202
+ if (!f.range) {
203
+ return;
204
+ }
205
+ let v$1 = filterDict[f.name + "From"];
206
+ if (v$1 !== undefined && v$1 !== null) {
207
+ whereParts.push(jsonTextC(f.name) + ` >= ` + param(b, Stdlib_Option.getOr(valString(v$1), "")));
208
+ }
209
+ let v$2 = filterDict[f.name + "To"];
210
+ if (v$2 !== undefined && v$2 !== null) {
211
+ whereParts.push(jsonTextC(f.name) + ` <= ` + param(b, Stdlib_Option.getOr(valString(v$2), "")));
212
+ return;
213
+ }
214
+ });
215
+ let orderByDict = Stdlib_Option.flatMap(argsDict["orderBy"], Stdlib_JSON.Decode.object);
216
+ let orderByField = Stdlib_Option.flatMap(Stdlib_Option.flatMap(orderByDict, ob => ob["field"]), Stdlib_JSON.Decode.string);
217
+ let isDesc = Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_Option.flatMap(orderByDict, ob => ob["direction"]), Stdlib_JSON.Decode.string), "ASC") === "DESC";
218
+ let cursorExpr = orderByField !== undefined ? jsonTextC(orderByField) : idExprC;
219
+ let c = Stdlib_Option.flatMap(argsDict["after"], Stdlib_JSON.Decode.string);
220
+ if (c !== undefined) {
221
+ whereParts.push(cursorExpr + ` ` + (
222
+ isDesc ? "<" : ">"
223
+ ) + ` ` + param(b, QueryDbListQuery$ReventlessCore.decodeCursor(c)));
224
+ }
225
+ let orderClause = orderByField !== undefined ? jsonTextC(orderByField) + ` ` + (
226
+ isDesc ? "DESC" : "ASC"
227
+ ) + `, ` + idExprC + ` ASC` : idExprC + ` ASC`;
228
+ let pageSize = Stdlib_Option.getOr(Stdlib_Option.map(Stdlib_Option.flatMap(argsDict["first"], Stdlib_JSON.Decode.float), prim => prim | 0), QueryDbListQuery$ReventlessCore.defaultListPageSize);
229
+ let sql = `SELECT partition_key, item FROM ` + table + ` WHERE ` + whereParts.join(" AND ") + ` ORDER BY ` + orderClause + ` LIMIT ` + param(b, pageSize + 1 | 0);
230
+ let rows = (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(true, extra));
231
+ let hasMore = rows.length > pageSize;
232
+ let pageItems = rows.slice(0, pageSize);
233
+ let cursorField = Stdlib_Option.getOr(orderByField, "id");
234
+ let cursorValueOf = item => Stdlib_Option.getOr(QueryDbListQuery$ReventlessCore.getFieldString(item, cursorField), QueryDbListQuery$ReventlessCore.getId(item));
235
+ return QueryDbListQuery$ReventlessCore.buildConnection(pageItems, hasMore, false, cursorValueOf);
236
+ };
237
+ let itemsPage = async (readModelName, param$1, id, argsDict, ownerScope) => {
238
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
239
+ let filterDict = Stdlib_Option.getOr(Stdlib_Option.flatMap(argsDict["filter"], Stdlib_JSON.Decode.object), {});
240
+ let fstr = k => Stdlib_Option.flatMap(filterDict[k], Stdlib_JSON.Decode.string);
241
+ let orderDesc = Stdlib_Option.mapOr(fstr("order"), false, o => o === "DESC");
242
+ let last = Stdlib_Option.map(Stdlib_Option.flatMap(argsDict["last"], Stdlib_JSON.Decode.float), prim => prim | 0);
243
+ let first = Stdlib_Option.map(Stdlib_Option.flatMap(argsDict["first"], Stdlib_JSON.Decode.float), prim => prim | 0);
244
+ let after = Stdlib_Option.flatMap(argsDict["after"], Stdlib_JSON.Decode.string);
245
+ let before = Stdlib_Option.flatMap(argsDict["before"], Stdlib_JSON.Decode.string);
246
+ let isBackward = Stdlib_Option.isSome(last);
247
+ let sk = `sub_key COLLATE "C"`;
248
+ let b = {
249
+ params: []
250
+ };
251
+ let where = [
252
+ `partition_key = ` + param(b, id),
253
+ QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause
254
+ ];
255
+ if (ownerScope !== undefined) {
256
+ where.push(jsonTextC(ownerScope[0]) + ` = ` + param(b, ownerScope[1]));
257
+ }
258
+ Stdlib_Option.forEach(fstr("prefix"), p => {
259
+ where.push(`starts_with(sub_key, ` + param(b, p) + `)`);
260
+ });
261
+ Stdlib_Option.forEach(fstr("from"), f => {
262
+ where.push(sk + ` >= ` + param(b, f));
263
+ });
264
+ Stdlib_Option.forEach(fstr("to"), t => {
265
+ where.push(sk + ` <= ` + param(b, t));
266
+ });
267
+ Stdlib_Option.forEach(fstr("eq"), e => {
268
+ where.push(sk + ` = ` + param(b, e));
269
+ });
270
+ if (isBackward) {
271
+ if (before !== undefined) {
272
+ where.push(sk + ` < ` + param(b, QueryDbListQuery$ReventlessCore.decodeCursor(before)));
273
+ }
274
+ } else if (after !== undefined) {
275
+ where.push(sk + ` > ` + param(b, QueryDbListQuery$ReventlessCore.decodeCursor(after)));
276
+ }
277
+ let fetchDesc = isBackward ? !orderDesc : orderDesc;
278
+ let pageSize = Stdlib_Option.getOr(isBackward ? last : first, QueryDbListQuery$ReventlessCore.defaultListPageSize);
279
+ let sql = `SELECT partition_key, sub_key, item FROM ` + table + ` WHERE ` + where.join(" AND ") + ` ORDER BY ` + sk + ` ` + (
280
+ fetchDesc ? "DESC" : "ASC"
281
+ ) + ` LIMIT ` + param(b, pageSize + 1 | 0);
282
+ let rows = await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params);
283
+ let hasMore = rows.length > pageSize;
284
+ let taken = rows.slice(0, pageSize);
285
+ let logical = isBackward ? taken.toReversed() : taken;
286
+ let pageItems = logical.map(extra => decodeRow(false, extra));
287
+ let subKeyOf = row => {
288
+ let match = row["sub_key"];
289
+ if (typeof match === "string") {
290
+ return match;
291
+ } else {
292
+ return "";
293
+ }
294
+ };
295
+ let cursors = logical.map(subKeyOf);
296
+ let edges = pageItems.map((item, i) => ({
297
+ node: item,
298
+ cursor: QueryDbListQuery$ReventlessCore.encodeCursor(cursors[i])
299
+ }));
300
+ let startCursor = Stdlib_Option.map(cursors[0], QueryDbListQuery$ReventlessCore.encodeCursor);
301
+ let endCursor = Stdlib_Option.map(cursors[cursors.length - 1 | 0], QueryDbListQuery$ReventlessCore.encodeCursor);
302
+ return {
303
+ edges: edges,
304
+ pageInfo: {
305
+ hasNextPage: !isBackward && hasMore,
306
+ hasPreviousPage: isBackward && hasMore,
307
+ startCursor: Stdlib_Nullable.fromOption(startCursor),
308
+ endCursor: Stdlib_Nullable.fromOption(endCursor)
309
+ }
310
+ };
311
+ };
152
312
  return {
153
313
  query: query,
154
314
  scan: scan,
155
- make: make
315
+ indexLookup: indexLookup,
316
+ byIds: byIds,
317
+ idExprC: idExprC,
318
+ jsonTextC: jsonTextC,
319
+ listPage: listPage,
320
+ itemsPage: itemsPage
156
321
  };
157
322
  }
158
323
 
159
- let notExpired = QueryDbStorage_Postgres$ReventlessPostgres.notExpiredClause;
324
+ let notExpired = QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause;
160
325
 
161
326
  export {
162
327
  valueToText,
@@ -169,4 +334,4 @@ export {
169
334
  decodeRow,
170
335
  Make,
171
336
  }
172
- /* @pulumi/pulumi Not a pure module */
337
+ /* PgDriver-ReventlessPostgres Not a pure module */
@@ -233,4 +233,72 @@ switch processEnv->Dict.get("PG_URL") {
233
233
  expect(again)->toBe(0)
234
234
  })
235
235
  })
236
+
237
+ describe("classic change feed (event_log, B2.5)", () => {
238
+ testPromise("drains classic events in commit order, with fields, then checkpoints", async () => {
239
+ let (_n, ops, _s) = EventLogStorage_Postgres.makeStorage(~pool, ~name="cf-orders", ~opts)
240
+ let _ = await ops.append(0, "agg-1", [evJson("m0", 1), evJson("m1", 2)])
241
+ let _ = await ops.append(0, "agg-2", [evJson("m2", 3)])
242
+
243
+ let collected = ref([])
244
+ let processed = await EventLogChangeFeed.drain(
245
+ pool,
246
+ ~logName="cf-orders",
247
+ ~subscriber="cf-sub",
248
+ ~handle=async evs => collected := collected.contents->Array.concat(evs),
249
+ )
250
+ expect(processed)->toBe(3)
251
+ expect(collected.contents->Array.length)->toBe(3)
252
+
253
+ // Fields round-trip from the stored row.
254
+ let first = collected.contents->Array.getUnsafe(0)
255
+ expect(first.aggregateId)->toBe("agg-1")
256
+ expect(first.seqNr)->toBe(0)
257
+ expect(first.msgId)->toEqual(Some("m0"))
258
+
259
+ // Cursors are strictly increasing in drain order.
260
+ let cursors = collected.contents->Array.map(e => e.cursor)
261
+ let increasing = ref(true)
262
+ for i in 1 to cursors->Array.length - 1 {
263
+ if cursors->Array.getUnsafe(i) <= cursors->Array.getUnsafe(i - 1) {
264
+ increasing := false
265
+ }
266
+ }
267
+ expect(increasing.contents)->toBe(true)
268
+
269
+ // Second drain from the saved checkpoint sees nothing new.
270
+ let again = await EventLogChangeFeed.drain(
271
+ pool,
272
+ ~logName="cf-orders",
273
+ ~subscriber="cf-sub",
274
+ ~handle=async _ => (),
275
+ )
276
+ expect(again)->toBe(0)
277
+ })
278
+
279
+ testPromise("concurrent appends across aggregates: every event drained exactly once", async () => {
280
+ let (_n, ops, _s) = EventLogStorage_Postgres.makeStorage(~pool, ~name="cf-concurrent", ~opts)
281
+ let n = 20
282
+ // One event per aggregate, all dispatched before awaiting — genuinely
283
+ // concurrent on the pool, so global_seq is assigned in interleaved/undefined
284
+ // commit order. The xmin fence must still drain every event exactly once.
285
+ let promises =
286
+ Array.make(~length=n, 0)->Array.mapWithIndex((_, i) =>
287
+ ops.append(0, "agg-" ++ Int.toString(i), [evJson("m" ++ Int.toString(i), i)])
288
+ )
289
+ let _ = await Promise.all(promises)
290
+
291
+ let collected = ref([])
292
+ let _ = await EventLogChangeFeed.drain(
293
+ pool,
294
+ ~logName="cf-concurrent",
295
+ ~subscriber="cf-conc-sub",
296
+ ~handle=async evs => collected := collected.contents->Array.concat(evs),
297
+ )
298
+ // No skips: all N events present. No dupes: N distinct cursors.
299
+ expect(collected.contents->Array.length)->toBe(n)
300
+ let distinctCursors = collected.contents->Array.map(e => e.cursor)->Set.fromArray
301
+ expect(distinctCursors->Set.size)->toBe(n)
302
+ })
303
+ })
236
304
  }
@@ -6,6 +6,7 @@ import * as Message$ReventlessCore from "@reventlessdev/reventless-core/src/Mess
6
6
  import * as PgDriver$ReventlessPostgres from "../src/PgDriver.res.mjs";
7
7
  import * as PgSchema$ReventlessPostgres from "../src/PgSchema.res.mjs";
8
8
  import * as PgChangeFeed$ReventlessPostgres from "../src/PgChangeFeed.res.mjs";
9
+ import * as EventLogChangeFeed$ReventlessPostgres from "../src/EventLogChangeFeed.res.mjs";
9
10
  import * as EventLogStorage_Postgres$ReventlessPostgres from "../src/EventLogStorage_Postgres.res.mjs";
10
11
  import * as DcbEventLogStorage_Postgres$ReventlessPostgres from "../src/DcbEventLogStorage_Postgres.res.mjs";
11
12
 
@@ -313,6 +314,54 @@ if (url !== undefined) {
313
314
  globalThis.expect(again).toBe(0);
314
315
  });
315
316
  });
317
+ globalThis.describe("classic change feed (event_log, B2.5)", () => {
318
+ globalThis.test("drains classic events in commit order, with fields, then checkpoints", async () => {
319
+ let match = EventLogStorage_Postgres$ReventlessPostgres.makeStorage(pool, "cf-orders", opts, undefined);
320
+ let ops = match[1];
321
+ await ops.append(0, "agg-1", [
322
+ evJson("m0", 1),
323
+ evJson("m1", 2)
324
+ ]);
325
+ await ops.append(0, "agg-2", [evJson("m2", 3)]);
326
+ let collected = {
327
+ contents: []
328
+ };
329
+ let processed = await EventLogChangeFeed$ReventlessPostgres.drain(pool, "cf-orders", "cf-sub", undefined, async evs => {
330
+ collected.contents = collected.contents.concat(evs);
331
+ });
332
+ globalThis.expect(processed).toBe(3);
333
+ globalThis.expect(collected.contents.length).toBe(3);
334
+ let first = collected.contents[0];
335
+ globalThis.expect(first.aggregateId).toBe("agg-1");
336
+ globalThis.expect(first.seqNr).toBe(0);
337
+ globalThis.expect(first.msgId).toEqual("m0");
338
+ let cursors = collected.contents.map(e => e.cursor);
339
+ let increasing = true;
340
+ for (let i = 1, i_finish = cursors.length; i < i_finish; ++i) {
341
+ if (cursors[i] <= cursors[i - 1 | 0]) {
342
+ increasing = false;
343
+ }
344
+ }
345
+ globalThis.expect(increasing).toBe(true);
346
+ let again = await EventLogChangeFeed$ReventlessPostgres.drain(pool, "cf-orders", "cf-sub", undefined, async param => {});
347
+ globalThis.expect(again).toBe(0);
348
+ });
349
+ globalThis.test("concurrent appends across aggregates: every event drained exactly once", async () => {
350
+ let match = EventLogStorage_Postgres$ReventlessPostgres.makeStorage(pool, "cf-concurrent", opts, undefined);
351
+ let ops = match[1];
352
+ let promises = Stdlib_Array.make(20, 0).map((param, i) => ops.append(0, "agg-" + i.toString(), [evJson("m" + i.toString(), i)]));
353
+ await Promise.all(promises);
354
+ let collected = {
355
+ contents: []
356
+ };
357
+ await EventLogChangeFeed$ReventlessPostgres.drain(pool, "cf-concurrent", "cf-conc-sub", undefined, async evs => {
358
+ collected.contents = collected.contents.concat(evs);
359
+ });
360
+ globalThis.expect(collected.contents.length).toBe(20);
361
+ let distinctCursors = new Set(collected.contents.map(e => e.cursor));
362
+ globalThis.expect(distinctCursors.size).toBe(20);
363
+ });
364
+ });
316
365
  } else {
317
366
  globalThis.test("Postgres integration (skipped — set PG_URL to run)", () => {
318
367
  globalThis.expect(true).toBe(true);