@reventlessdev/reventless-postgres 3.0.0-alpha.5 → 3.0.0-alpha.50

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 (158) hide show
  1. package/CHANGELOG.md +361 -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 +3 -2
  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.cmt +0 -0
  22. package/lib/bs/src/EventLogChangeFeed.ast +0 -0
  23. package/lib/bs/src/EventLogChangeFeed.res +5 -2
  24. package/lib/bs/src/EventLogChangeFeed.res.mjs +3 -3
  25. package/lib/bs/src/EventLogStorage_Postgres-ReventlessPostgres.cmi +0 -0
  26. package/lib/bs/src/EventLogStorage_Postgres-ReventlessPostgres.cmj +0 -0
  27. package/lib/bs/src/EventLogStorage_Postgres-ReventlessPostgres.cmt +0 -0
  28. package/lib/bs/src/EventLogStorage_Postgres.ast +0 -0
  29. package/lib/bs/src/EventLogStorage_Postgres.res +12 -170
  30. package/lib/bs/src/EventLogStorage_Postgres.res.mjs +20 -186
  31. package/lib/bs/src/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
  32. package/lib/bs/src/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
  33. package/lib/bs/src/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
  34. package/lib/bs/src/EventLogStorage_Postgres_Ops.ast +0 -0
  35. package/lib/bs/src/EventLogStorage_Postgres_Ops.res +180 -0
  36. package/lib/bs/src/EventLogStorage_Postgres_Ops.res.mjs +202 -0
  37. package/lib/bs/src/PgChangeFeed-ReventlessPostgres.cmi +0 -0
  38. package/lib/bs/src/PgChangeFeed-ReventlessPostgres.cmt +0 -0
  39. package/lib/bs/src/PgChangeFeed.ast +0 -0
  40. package/lib/bs/src/PgChangeFeed.res +6 -1
  41. package/lib/bs/src/PgChangeFeed.res.mjs +6 -6
  42. package/lib/bs/src/PgDriver-ReventlessPostgres.cmi +0 -0
  43. package/lib/bs/src/PgDriver-ReventlessPostgres.cmt +0 -0
  44. package/lib/bs/src/PgDriver-ReventlessPostgres.cmti +0 -0
  45. package/lib/bs/src/PgDriver.ast +0 -0
  46. package/lib/bs/src/PgDriver.iast +0 -0
  47. package/lib/bs/src/PgSchema-ReventlessPostgres.cmi +0 -0
  48. package/lib/bs/src/PgSchema-ReventlessPostgres.cmt +0 -0
  49. package/lib/bs/src/PgSchema.ast +0 -0
  50. package/lib/bs/src/QueryDbStorage_Postgres-ReventlessPostgres.cmi +0 -0
  51. package/lib/bs/src/QueryDbStorage_Postgres-ReventlessPostgres.cmt +0 -0
  52. package/lib/bs/src/QueryDbStorage_Postgres.ast +0 -0
  53. package/lib/bs/src/QueryDbStorage_Postgres.res +10 -233
  54. package/lib/bs/src/QueryDbStorage_Postgres.res.mjs +25 -204
  55. package/lib/bs/src/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
  56. package/lib/bs/src/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
  57. package/lib/bs/src/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
  58. package/lib/bs/src/QueryDbStorage_Postgres_Ops.ast +0 -0
  59. package/lib/bs/src/QueryDbStorage_Postgres_Ops.res +229 -0
  60. package/lib/bs/src/QueryDbStorage_Postgres_Ops.res.mjs +222 -0
  61. package/lib/bs/src/QueryEnginePostgres-ReventlessPostgres.cmi +0 -0
  62. package/lib/bs/src/QueryEnginePostgres-ReventlessPostgres.cmt +0 -0
  63. package/lib/bs/src/QueryEnginePostgres.ast +0 -0
  64. package/lib/bs/src/QueryEnginePostgres.res +91 -10
  65. package/lib/bs/src/QueryEnginePostgres.res.mjs +89 -21
  66. package/lib/bs/tests/PostgresIntegrationTest-ReventlessPostgres.cmi +0 -0
  67. package/lib/bs/tests/PostgresIntegrationTest-ReventlessPostgres.cmt +0 -0
  68. package/lib/bs/tests/PostgresIntegrationTest.ast +0 -0
  69. package/lib/bs/tests/QueryEnginePostgresListPageTest-ReventlessPostgres.cmi +0 -0
  70. package/lib/bs/tests/QueryEnginePostgresListPageTest-ReventlessPostgres.cmt +0 -0
  71. package/lib/bs/tests/QueryEnginePostgresListPageTest.ast +0 -0
  72. package/lib/bs/tests/QueryEnginePostgresListPageTest.res +76 -0
  73. package/lib/bs/tests/QueryEnginePostgresListPageTest.res.mjs +136 -0
  74. package/lib/ocaml/.compiler.log +2 -2
  75. package/lib/ocaml/DcbEventLogStorage_Postgres-ReventlessPostgres.cmi +0 -0
  76. package/lib/ocaml/DcbEventLogStorage_Postgres-ReventlessPostgres.cmj +0 -0
  77. package/lib/ocaml/DcbEventLogStorage_Postgres-ReventlessPostgres.cmt +0 -0
  78. package/lib/ocaml/DcbEventLogStorage_Postgres.ast +0 -0
  79. package/lib/ocaml/DcbEventLogStorage_Postgres.res +25 -340
  80. package/lib/ocaml/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
  81. package/lib/ocaml/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
  82. package/lib/ocaml/DcbEventLogStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
  83. package/lib/ocaml/DcbEventLogStorage_Postgres_Ops.ast +0 -0
  84. package/lib/ocaml/DcbEventLogStorage_Postgres_Ops.res +350 -0
  85. package/lib/ocaml/EventLogChangeFeed-ReventlessPostgres.cmi +0 -0
  86. package/lib/ocaml/EventLogChangeFeed-ReventlessPostgres.cmt +0 -0
  87. package/lib/ocaml/EventLogChangeFeed.ast +0 -0
  88. package/lib/ocaml/EventLogChangeFeed.res +5 -2
  89. package/lib/ocaml/EventLogStorage_Postgres-ReventlessPostgres.cmi +0 -0
  90. package/lib/ocaml/EventLogStorage_Postgres-ReventlessPostgres.cmj +0 -0
  91. package/lib/ocaml/EventLogStorage_Postgres-ReventlessPostgres.cmt +0 -0
  92. package/lib/ocaml/EventLogStorage_Postgres.ast +0 -0
  93. package/lib/ocaml/EventLogStorage_Postgres.res +12 -170
  94. package/lib/ocaml/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
  95. package/lib/ocaml/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
  96. package/lib/ocaml/EventLogStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
  97. package/lib/ocaml/EventLogStorage_Postgres_Ops.ast +0 -0
  98. package/lib/ocaml/EventLogStorage_Postgres_Ops.res +180 -0
  99. package/lib/ocaml/PgChangeFeed-ReventlessPostgres.cmi +0 -0
  100. package/lib/ocaml/PgChangeFeed-ReventlessPostgres.cmt +0 -0
  101. package/lib/ocaml/PgChangeFeed.ast +0 -0
  102. package/lib/ocaml/PgChangeFeed.res +6 -1
  103. package/lib/ocaml/PgDriver-ReventlessPostgres.cmi +0 -0
  104. package/lib/ocaml/PgDriver-ReventlessPostgres.cmt +0 -0
  105. package/lib/ocaml/PgDriver-ReventlessPostgres.cmti +0 -0
  106. package/lib/ocaml/PgDriver.ast +0 -0
  107. package/lib/ocaml/PgDriver.iast +0 -0
  108. package/lib/ocaml/PgSchema-ReventlessPostgres.cmi +0 -0
  109. package/lib/ocaml/PgSchema-ReventlessPostgres.cmt +0 -0
  110. package/lib/ocaml/PgSchema.ast +0 -0
  111. package/lib/ocaml/QueryDbStorage_Postgres-ReventlessPostgres.cmi +0 -0
  112. package/lib/ocaml/QueryDbStorage_Postgres-ReventlessPostgres.cmt +0 -0
  113. package/lib/ocaml/QueryDbStorage_Postgres.ast +0 -0
  114. package/lib/ocaml/QueryDbStorage_Postgres.res +10 -233
  115. package/lib/ocaml/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmi +0 -0
  116. package/lib/ocaml/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmj +0 -0
  117. package/lib/ocaml/QueryDbStorage_Postgres_Ops-ReventlessPostgres.cmt +0 -0
  118. package/lib/ocaml/QueryDbStorage_Postgres_Ops.ast +0 -0
  119. package/lib/ocaml/QueryDbStorage_Postgres_Ops.res +229 -0
  120. package/lib/ocaml/QueryEnginePostgres-ReventlessPostgres.cmi +0 -0
  121. package/lib/ocaml/QueryEnginePostgres-ReventlessPostgres.cmt +0 -0
  122. package/lib/ocaml/QueryEnginePostgres.ast +0 -0
  123. package/lib/ocaml/QueryEnginePostgres.res +91 -10
  124. package/lib/ocaml/QueryEnginePostgresListPageTest.res +76 -0
  125. package/lib/ocaml/ReventlessPostgres.cmi +0 -0
  126. package/lib/ocaml/ReventlessPostgres.cmt +0 -0
  127. package/lib/ocaml/ReventlessPostgres.mlmap +3 -0
  128. package/package.json +11 -11
  129. package/rescript.json +2 -1
  130. package/src/DcbEventLogStorage_Postgres.res +25 -340
  131. package/src/DcbEventLogStorage_Postgres.res.mjs +32 -348
  132. package/src/DcbEventLogStorage_Postgres_Ops.res +350 -0
  133. package/src/DcbEventLogStorage_Postgres_Ops.res.mjs +380 -0
  134. package/src/EventLogChangeFeed.res +5 -2
  135. package/src/EventLogChangeFeed.res.mjs +3 -3
  136. package/src/EventLogStorage_Postgres.res +12 -170
  137. package/src/EventLogStorage_Postgres.res.mjs +20 -186
  138. package/src/EventLogStorage_Postgres_Ops.res +180 -0
  139. package/src/EventLogStorage_Postgres_Ops.res.mjs +202 -0
  140. package/src/PgChangeFeed.res +6 -1
  141. package/src/PgChangeFeed.res.mjs +6 -6
  142. package/src/QueryDbStorage_Postgres.res +10 -233
  143. package/src/QueryDbStorage_Postgres.res.mjs +25 -204
  144. package/src/QueryDbStorage_Postgres_Ops.res +229 -0
  145. package/src/QueryDbStorage_Postgres_Ops.res.mjs +222 -0
  146. package/src/QueryEnginePostgres.res +91 -10
  147. package/src/QueryEnginePostgres.res.mjs +89 -21
  148. package/tests/QueryEnginePostgresListPageTest.res +76 -0
  149. package/lib/ocaml/PostgresIntegrationTest-ReventlessPostgres.cmi +0 -0
  150. package/lib/ocaml/PostgresIntegrationTest-ReventlessPostgres.cmj +0 -0
  151. package/lib/ocaml/PostgresIntegrationTest-ReventlessPostgres.cmt +0 -0
  152. package/lib/ocaml/PostgresIntegrationTest.ast +0 -0
  153. package/lib/ocaml/QueryEnginePostgresListPageTest-ReventlessPostgres.cmi +0 -0
  154. package/lib/ocaml/QueryEnginePostgresListPageTest-ReventlessPostgres.cmj +0 -0
  155. package/lib/ocaml/QueryEnginePostgresListPageTest-ReventlessPostgres.cmt +0 -0
  156. package/lib/ocaml/QueryEnginePostgresListPageTest.ast +0 -0
  157. package/tests/PostgresIntegrationTest.res.mjs +0 -377
  158. package/tests/QueryEnginePostgresListPageTest.res.mjs +0 -325
@@ -2,10 +2,10 @@
2
2
 
3
3
  import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
4
4
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
- import * as Pulumi from "@pulumi/pulumi";
5
+ import * as Stdlib_Nullable from "@rescript/runtime/lib/es6/Stdlib_Nullable.js";
6
6
  import * as PgDriver$ReventlessPostgres from "./PgDriver.res.mjs";
7
7
  import * as QueryDbListQuery$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/QueryDbListQuery.res.mjs";
8
- import * as QueryDbStorage_Postgres$ReventlessPostgres from "./QueryDbStorage_Postgres.res.mjs";
8
+ import * as QueryDbStorage_Postgres_Ops$ReventlessPostgres from "./QueryDbStorage_Postgres_Ops.res.mjs";
9
9
 
10
10
  function valueToText(v) {
11
11
  switch (v.TAG) {
@@ -104,25 +104,25 @@ function subIdSql(b, field, cmp, v) {
104
104
  }
105
105
 
106
106
  function decodeRow(withId, row) {
107
- let item = QueryDbStorage_Postgres$ReventlessPostgres.decodeItem(row);
107
+ let item = QueryDbStorage_Postgres_Ops$ReventlessPostgres.decodeItem(row);
108
108
  if (!withId) {
109
109
  return item;
110
110
  }
111
111
  let match = row["partition_key"];
112
112
  let pk = typeof match === "string" ? match : "";
113
- return QueryDbStorage_Postgres$ReventlessPostgres.withId(item, pk);
113
+ return QueryDbStorage_Postgres_Ops$ReventlessPostgres.withId(item, pk);
114
114
  }
115
115
 
116
116
  function Make(P) {
117
117
  let query = async (readModelName, key, id, subIdConfig, filterConfigs, ascending, limit) => {
118
- let table = QueryDbStorage_Postgres$ReventlessPostgres.tableName(readModelName);
118
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
119
119
  let keyStr = key !== undefined ? key : valueToText(id);
120
120
  let b = {
121
121
  params: []
122
122
  };
123
123
  let where = [
124
124
  `partition_key = ` + param(b, keyStr),
125
- QueryDbStorage_Postgres$ReventlessPostgres.notExpiredClause
125
+ QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause
126
126
  ];
127
127
  if (subIdConfig !== undefined) {
128
128
  where.push(subIdSql(b, subIdConfig[0], subIdConfig[1], subIdConfig[2]));
@@ -136,11 +136,11 @@ function Make(P) {
136
136
  return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(false, extra));
137
137
  };
138
138
  let scan = async (readModelName, filterConfigs, limit) => {
139
- let table = QueryDbStorage_Postgres$ReventlessPostgres.tableName(readModelName);
139
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
140
140
  let b = {
141
141
  params: []
142
142
  };
143
- let where = [QueryDbStorage_Postgres$ReventlessPostgres.notExpiredClause];
143
+ let where = [QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause];
144
144
  filterConfigs.forEach(param => {
145
145
  where.push(filterSql(b, param[0], param[1], param[2]));
146
146
  });
@@ -148,29 +148,29 @@ function Make(P) {
148
148
  return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(true, extra));
149
149
  };
150
150
  let indexLookup = async (readModelName, field, value) => {
151
- let table = QueryDbStorage_Postgres$ReventlessPostgres.tableName(readModelName);
151
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
152
152
  let b = {
153
153
  params: []
154
154
  };
155
- let sql = `SELECT partition_key, item FROM ` + table + ` WHERE ` + col(field) + ` = ` + param(b, value) + ` AND ` + QueryDbStorage_Postgres$ReventlessPostgres.notExpiredClause;
155
+ let sql = `SELECT partition_key, item FROM ` + table + ` WHERE ` + col(field) + ` = ` + param(b, value) + ` AND ` + QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause;
156
156
  return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(true, extra));
157
157
  };
158
158
  let byIds = async (readModelName, ids) => {
159
159
  if (ids.length === 0) {
160
160
  return [];
161
161
  }
162
- let table = QueryDbStorage_Postgres$ReventlessPostgres.tableName(readModelName);
162
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
163
163
  let b = {
164
164
  params: []
165
165
  };
166
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$ReventlessPostgres.notExpiredClause;
167
+ let sql = `SELECT partition_key, item FROM ` + table + ` WHERE partition_key = ANY(` + param(b, idsJson) + `::text[]) AND ` + QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause;
168
168
  return (await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params)).map(extra => decodeRow(true, extra));
169
169
  };
170
170
  let idExprC = `COALESCE(item->>'id', partition_key) COLLATE "C"`;
171
171
  let jsonTextC = field => col(field) + ` COLLATE "C"`;
172
172
  let listPage = async (readModelName, argsDict, capability, param$1) => {
173
- let table = QueryDbStorage_Postgres$ReventlessPostgres.tableName(readModelName);
173
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
174
174
  let filterDict = Stdlib_Option.getOr(Stdlib_Option.flatMap(argsDict["filter"], Stdlib_JSON.Decode.object), {});
175
175
  let strNonEmpty = k => Stdlib_Option.mapOr(Stdlib_Option.flatMap(filterDict[k], Stdlib_JSON.Decode.string), false, s => s.length > 0);
176
176
  let hasIds = Stdlib_Option.mapOr(Stdlib_Option.flatMap(filterDict["ids"], Stdlib_JSON.Decode.array), false, a => a.length !== 0);
@@ -182,7 +182,7 @@ function Make(P) {
182
182
  let b = {
183
183
  params: []
184
184
  };
185
- let whereParts = [QueryDbStorage_Postgres$ReventlessPostgres.notExpiredClause];
185
+ let whereParts = [QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause];
186
186
  let valString = v => {
187
187
  let s = Stdlib_JSON.Decode.string(v);
188
188
  if (s !== undefined) {
@@ -231,10 +231,78 @@ function Make(P) {
231
231
  let cursorValueOf = item => Stdlib_Option.getOr(QueryDbListQuery$ReventlessCore.getFieldString(item, cursorField), QueryDbListQuery$ReventlessCore.getId(item));
232
232
  return QueryDbListQuery$ReventlessCore.buildConnection(pageItems, hasMore, false, cursorValueOf);
233
233
  };
234
- let make = _allQueryDbs => Pulumi.output({
235
- scan: scan,
236
- query: query
237
- });
234
+ let itemsPage = async (readModelName, param$1, id, argsDict) => {
235
+ let table = QueryDbStorage_Postgres_Ops$ReventlessPostgres.tableName(readModelName);
236
+ let filterDict = Stdlib_Option.getOr(Stdlib_Option.flatMap(argsDict["filter"], Stdlib_JSON.Decode.object), {});
237
+ let fstr = k => Stdlib_Option.flatMap(filterDict[k], Stdlib_JSON.Decode.string);
238
+ let orderDesc = Stdlib_Option.mapOr(fstr("order"), false, o => o === "DESC");
239
+ let last = Stdlib_Option.map(Stdlib_Option.flatMap(argsDict["last"], Stdlib_JSON.Decode.float), prim => prim | 0);
240
+ let first = Stdlib_Option.map(Stdlib_Option.flatMap(argsDict["first"], Stdlib_JSON.Decode.float), prim => prim | 0);
241
+ let after = Stdlib_Option.flatMap(argsDict["after"], Stdlib_JSON.Decode.string);
242
+ let before = Stdlib_Option.flatMap(argsDict["before"], Stdlib_JSON.Decode.string);
243
+ let isBackward = Stdlib_Option.isSome(last);
244
+ let sk = `sub_key COLLATE "C"`;
245
+ let b = {
246
+ params: []
247
+ };
248
+ let where = [
249
+ `partition_key = ` + param(b, id),
250
+ QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause
251
+ ];
252
+ Stdlib_Option.forEach(fstr("prefix"), p => {
253
+ where.push(`starts_with(sub_key, ` + param(b, p) + `)`);
254
+ });
255
+ Stdlib_Option.forEach(fstr("from"), f => {
256
+ where.push(sk + ` >= ` + param(b, f));
257
+ });
258
+ Stdlib_Option.forEach(fstr("to"), t => {
259
+ where.push(sk + ` <= ` + param(b, t));
260
+ });
261
+ Stdlib_Option.forEach(fstr("eq"), e => {
262
+ where.push(sk + ` = ` + param(b, e));
263
+ });
264
+ if (isBackward) {
265
+ if (before !== undefined) {
266
+ where.push(sk + ` < ` + param(b, QueryDbListQuery$ReventlessCore.decodeCursor(before)));
267
+ }
268
+ } else if (after !== undefined) {
269
+ where.push(sk + ` > ` + param(b, QueryDbListQuery$ReventlessCore.decodeCursor(after)));
270
+ }
271
+ let fetchDesc = isBackward ? !orderDesc : orderDesc;
272
+ let pageSize = Stdlib_Option.getOr(isBackward ? last : first, QueryDbListQuery$ReventlessCore.defaultListPageSize);
273
+ let sql = `SELECT partition_key, sub_key, item FROM ` + table + ` WHERE ` + where.join(" AND ") + ` ORDER BY ` + sk + ` ` + (
274
+ fetchDesc ? "DESC" : "ASC"
275
+ ) + ` LIMIT ` + param(b, pageSize + 1 | 0);
276
+ let rows = await PgDriver$ReventlessPostgres.query(P.pool, sql, b.params);
277
+ let hasMore = rows.length > pageSize;
278
+ let taken = rows.slice(0, pageSize);
279
+ let logical = isBackward ? taken.toReversed() : taken;
280
+ let pageItems = logical.map(extra => decodeRow(false, extra));
281
+ let subKeyOf = row => {
282
+ let match = row["sub_key"];
283
+ if (typeof match === "string") {
284
+ return match;
285
+ } else {
286
+ return "";
287
+ }
288
+ };
289
+ let cursors = logical.map(subKeyOf);
290
+ let edges = pageItems.map((item, i) => ({
291
+ node: item,
292
+ cursor: QueryDbListQuery$ReventlessCore.encodeCursor(cursors[i])
293
+ }));
294
+ let startCursor = Stdlib_Option.map(cursors[0], QueryDbListQuery$ReventlessCore.encodeCursor);
295
+ let endCursor = Stdlib_Option.map(cursors[cursors.length - 1 | 0], QueryDbListQuery$ReventlessCore.encodeCursor);
296
+ return {
297
+ edges: edges,
298
+ pageInfo: {
299
+ hasNextPage: !isBackward && hasMore,
300
+ hasPreviousPage: isBackward && hasMore,
301
+ startCursor: Stdlib_Nullable.fromOption(startCursor),
302
+ endCursor: Stdlib_Nullable.fromOption(endCursor)
303
+ }
304
+ };
305
+ };
238
306
  return {
239
307
  query: query,
240
308
  scan: scan,
@@ -243,11 +311,11 @@ function Make(P) {
243
311
  idExprC: idExprC,
244
312
  jsonTextC: jsonTextC,
245
313
  listPage: listPage,
246
- make: make
314
+ itemsPage: itemsPage
247
315
  };
248
316
  }
249
317
 
250
- let notExpired = QueryDbStorage_Postgres$ReventlessPostgres.notExpiredClause;
318
+ let notExpired = QueryDbStorage_Postgres_Ops$ReventlessPostgres.notExpiredClause;
251
319
 
252
320
  export {
253
321
  valueToText,
@@ -260,4 +328,4 @@ export {
260
328
  decodeRow,
261
329
  Make,
262
330
  }
263
- /* @pulumi/pulumi Not a pure module */
331
+ /* PgDriver-ReventlessPostgres Not a pure module */
@@ -233,4 +233,80 @@ switch processEnv->Dict.get("PG_URL") {
233
233
  expect(items->Array.length)->toBe(0)
234
234
  })
235
235
  })
236
+
237
+ // ── itemsPage (sub-id connection) ─────────────────────────────────────────
238
+ // A sub-id read model: partition "order-1" holds 5 lines keyed by `seq`.
239
+ let itemsName = "itemsparity"
240
+ let mkLine = seq => {
241
+ let o = Dict.make()
242
+ o->Dict.set("id", JSON.Encode.string("order-1"))
243
+ o->Dict.set("seq", JSON.Encode.string(seq))
244
+ JSON.Encode.object(o)
245
+ }
246
+ let seqs = ["a", "b", "c", "d", "e"]
247
+ beforeAllAsync(async () => {
248
+ let ops = QueryDbStorage_Postgres.makeOperations(
249
+ ~pool,
250
+ ~name=itemsName,
251
+ ~indexes=[],
252
+ ~subIdField=Some("seq"),
253
+ )
254
+ for i in 0 to seqs->Array.length - 1 {
255
+ let _ = await ops.save("order-1", mkLine(seqs->Array.getUnsafe(i)), QueryDb.Any, None)
256
+ }
257
+ })
258
+
259
+ // Extract node `seq` values in edge order.
260
+ let itemSeqs = (conn: JSON.t) =>
261
+ conn
262
+ ->field("edges")
263
+ ->Option.flatMap(JSON.Decode.array)
264
+ ->Option.getOr([])
265
+ ->Array.filterMap(e => e->field("node")->Option.flatMap(n => n->str("seq")))
266
+
267
+ let pageInfoBool = (conn, key) =>
268
+ conn->field("pageInfo")->Option.getOr(JSON.Encode.null)->field(key)->Option.flatMap(JSON.Decode.bool)->Option.getOr(false)
269
+
270
+ let itemsPage = args =>
271
+ Eng.itemsPage(~readModelName=itemsName, ~subIdField="seq", ~id="order-1", ~argsDict=argsOf(args))
272
+
273
+ describe("QueryEnginePostgres itemsPage (sub-id keyset)", () => {
274
+ testPromise("bare → all lines ASC, no next page", async () => {
275
+ let r = await itemsPage([])
276
+ expect(r->itemSeqs)->toEqual(["a", "b", "c", "d", "e"])
277
+ expect(pageInfoBool(r, "hasNextPage"))->toBe(false)
278
+ })
279
+ testPromise("first:2 → [a,b], hasNextPage", async () => {
280
+ let r = await itemsPage([("first", JSON.Encode.int(2))])
281
+ expect(r->itemSeqs)->toEqual(["a", "b"])
282
+ expect(pageInfoBool(r, "hasNextPage"))->toBe(true)
283
+ })
284
+ testPromise("first:2 after b → [c,d]", async () => {
285
+ let r = await itemsPage([("first", JSON.Encode.int(2)), ("after", JSON.Encode.string(cur("b")))])
286
+ expect(r->itemSeqs)->toEqual(["c", "d"])
287
+ })
288
+ testPromise("order DESC → [e..a]", async () => {
289
+ let r = await itemsPage([("filter", filterOf([("order", JSON.Encode.string("DESC"))]))])
290
+ expect(r->itemSeqs)->toEqual(["e", "d", "c", "b", "a"])
291
+ })
292
+ testPromise("filter eq c → [c]", async () => {
293
+ let r = await itemsPage([("filter", filterOf([("eq", JSON.Encode.string("c"))]))])
294
+ expect(r->itemSeqs)->toEqual(["c"])
295
+ })
296
+ testPromise("filter from b to d → [b,c,d]", async () => {
297
+ let r = await itemsPage([
298
+ ("filter", filterOf([("from", JSON.Encode.string("b")), ("to", JSON.Encode.string("d"))])),
299
+ ])
300
+ expect(r->itemSeqs)->toEqual(["b", "c", "d"])
301
+ })
302
+ testPromise("prefix c → [c]", async () => {
303
+ let r = await itemsPage([("filter", filterOf([("prefix", JSON.Encode.string("c"))]))])
304
+ expect(r->itemSeqs)->toEqual(["c"])
305
+ })
306
+ testPromise("backward last:2 before d → [b,c] (logical ASC)", async () => {
307
+ let r = await itemsPage([("last", JSON.Encode.int(2)), ("before", JSON.Encode.string(cur("d")))])
308
+ expect(r->itemSeqs)->toEqual(["b", "c"])
309
+ expect(pageInfoBool(r, "hasPreviousPage"))->toBe(true)
310
+ })
311
+ })
236
312
  }
@@ -1,377 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
4
- import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
5
- import * as Message$ReventlessCore from "@reventlessdev/reventless-core/src/Message.res.mjs";
6
- import * as PgDriver$ReventlessPostgres from "../src/PgDriver.res.mjs";
7
- import * as PgSchema$ReventlessPostgres from "../src/PgSchema.res.mjs";
8
- import * as PgChangeFeed$ReventlessPostgres from "../src/PgChangeFeed.res.mjs";
9
- import * as EventLogChangeFeed$ReventlessPostgres from "../src/EventLogChangeFeed.res.mjs";
10
- import * as EventLogStorage_Postgres$ReventlessPostgres from "../src/EventLogStorage_Postgres.res.mjs";
11
- import * as DcbEventLogStorage_Postgres$ReventlessPostgres from "../src/DcbEventLogStorage_Postgres.res.mjs";
12
-
13
- let opts = {};
14
-
15
- function jsonObj(pairs) {
16
- return Object.fromEntries(pairs);
17
- }
18
-
19
- function stored(eventType, tags, data) {
20
- return {
21
- eventType: eventType,
22
- data: data,
23
- tags: tags,
24
- meta: Message$ReventlessCore.generateMeta("pg-test", undefined, undefined, undefined, undefined, undefined, undefined, undefined)
25
- };
26
- }
27
-
28
- function evJson(msgId, v) {
29
- return Object.fromEntries([
30
- [
31
- "msgId",
32
- msgId
33
- ],
34
- [
35
- "v",
36
- v
37
- ]
38
- ]);
39
- }
40
-
41
- let url = process.env["PG_URL"];
42
-
43
- if (url !== undefined) {
44
- let pool = PgDriver$ReventlessPostgres.makePool({
45
- connectionString: url
46
- });
47
- globalThis.beforeAll(async () => {
48
- await PgSchema$ReventlessPostgres.ensureSchema(pool);
49
- return await PgSchema$ReventlessPostgres.truncateAll(pool);
50
- });
51
- globalThis.afterAll(() => {
52
- PgDriver$ReventlessPostgres.endPool(pool);
53
- });
54
- globalThis.describe("classic OCC event log", () => {
55
- globalThis.test("append, replay, and conflict on wrong seq", async () => {
56
- let match = EventLogStorage_Postgres$ReventlessPostgres.makeStorage(pool, "ct-orders", opts, undefined);
57
- let ops = match[1];
58
- let r0 = await ops.append(0, "agg-1", [
59
- evJson("m0", 1),
60
- evJson("m1", 2)
61
- ]);
62
- if (r0.TAG === "Ok") {
63
- globalThis.expect(true).toBe(true);
64
- } else {
65
- globalThis.expect("append").toBe("ok");
66
- }
67
- let rStale = await ops.append(0, "agg-1", [evJson("m2", 3)]);
68
- if (rStale.TAG === "Ok") {
69
- globalThis.expect("stale").toBe("conflict");
70
- } else {
71
- let tmp = rStale._0;
72
- if (typeof tmp !== "object") {
73
- globalThis.expect(true).toBe(true);
74
- } else {
75
- globalThis.expect("stale").toBe("conflict");
76
- }
77
- }
78
- let rGap = await ops.append(5, "agg-1", [evJson("m3", 4)]);
79
- if (rGap.TAG === "Ok") {
80
- globalThis.expect("gap").toBe("conflict");
81
- } else {
82
- let tmp$1 = rGap._0;
83
- if (typeof tmp$1 !== "object") {
84
- globalThis.expect(true).toBe(true);
85
- } else {
86
- globalThis.expect("gap").toBe("conflict");
87
- }
88
- }
89
- let rNext = await ops.append(2, "agg-1", [evJson("m4", 5)]);
90
- if (rNext.TAG === "Ok") {
91
- globalThis.expect(true).toBe(true);
92
- } else {
93
- globalThis.expect("next").toBe("ok");
94
- }
95
- let evs = await ops.replay("agg-1");
96
- globalThis.expect(evs.length).toBe(3);
97
- let rEmpty = await ops.append(3, "agg-1", []);
98
- if (rEmpty.TAG === "Ok") {
99
- globalThis.expect(true).toBe(true);
100
- return;
101
- }
102
- globalThis.expect("empty").toBe("ok");
103
- });
104
- });
105
- globalThis.describe("DCB event log", () => {
106
- let makeLog = name => DcbEventLogStorage_Postgres$ReventlessPostgres.makeStorage(pool, name, [], {
107
- TAG: "Simple",
108
- _0: {
109
- key: "k"
110
- }
111
- }, undefined, opts, undefined, undefined);
112
- globalThis.test("append + read round-trips events with tags", async () => {
113
- let match = makeLog("dcb-rt");
114
- let ops = match[1];
115
- let e1 = stored("ItemAdded", [{
116
- key: "itemId",
117
- value: "x1"
118
- }], Object.fromEntries([[
119
- "n",
120
- "w"
121
- ]]));
122
- let r = await ops.append([e1], undefined);
123
- if (r.TAG === "Ok") {
124
- globalThis.expect(true).toBe(true);
125
- } else {
126
- globalThis.expect(r._0).toBe("ok");
127
- }
128
- let read = await ops.read([], undefined);
129
- globalThis.expect(read.events.length).toBe(1);
130
- let first = read.events[0];
131
- globalThis.expect(first.eventType).toBe("ItemAdded");
132
- globalThis.expect(first.tags[0].key).toBe("itemId");
133
- globalThis.expect(first.tags[0].value).toBe("x1");
134
- });
135
- globalThis.test("conditional append conflicts when the boundary already has an event", async () => {
136
- let match = makeLog("dcb-cond");
137
- let ops = match[1];
138
- let mk = who => stored("Reserved", [{
139
- key: "seatId",
140
- value: "s1"
141
- }], Object.fromEntries([[
142
- "who",
143
- who
144
- ]]));
145
- let r1 = await ops.append([mk("a")], undefined);
146
- if (r1.TAG === "Ok") {
147
- globalThis.expect(true).toBe(true);
148
- } else {
149
- globalThis.expect("first").toBe("ok");
150
- }
151
- let cond_query = [{
152
- eventTypes: ["Reserved"],
153
- tags: [{
154
- key: "seatId",
155
- value: "s1"
156
- }]
157
- }];
158
- let cond = {
159
- query: cond_query
160
- };
161
- let r2 = await ops.append([mk("b")], cond);
162
- if (r2.TAG === "Ok") {
163
- globalThis.expect("second").toBe("conflict");
164
- return;
165
- }
166
- let tmp = r2._0;
167
- if (typeof tmp !== "object") {
168
- globalThis.expect(true).toBe(true);
169
- return;
170
- }
171
- globalThis.expect("second").toBe("conflict");
172
- });
173
- let writeSkew = (strategy, logName) => {
174
- globalThis.test(`write-skew: exactly one of two concurrent appends wins (` + logName + `)`, async () => {
175
- let match = DcbEventLogStorage_Postgres$ReventlessPostgres.makeStorage(pool, logName, [], {
176
- TAG: "Simple",
177
- _0: {
178
- key: "k"
179
- }
180
- }, undefined, opts, strategy, undefined);
181
- let ops = match[1];
182
- let cond_query = [{
183
- eventTypes: ["Reserved"],
184
- tags: [{
185
- key: "seatId",
186
- value: "hot"
187
- }]
188
- }];
189
- let cond = {
190
- query: cond_query
191
- };
192
- let mk = who => stored("Reserved", [{
193
- key: "seatId",
194
- value: "hot"
195
- }], Object.fromEntries([[
196
- "who",
197
- who
198
- ]]));
199
- let p1 = ops.append([mk("a")], cond);
200
- let p2 = ops.append([mk("b")], cond);
201
- let r1 = await p1;
202
- let r2 = await p2;
203
- let isOk = r => r.TAG === "Ok";
204
- let isConflict = r => Primitive_object.equal(r, {
205
- TAG: "Error",
206
- _0: "Conflict"
207
- });
208
- let oks = [
209
- r1,
210
- r2
211
- ].filter(isOk).length;
212
- let conflicts = [
213
- r1,
214
- r2
215
- ].filter(isConflict).length;
216
- globalThis.expect(oks).toBe(1);
217
- globalThis.expect(conflicts).toBe(1);
218
- let read = await ops.read([{
219
- tags: [{
220
- key: "seatId",
221
- value: "hot"
222
- }]
223
- }], undefined);
224
- globalThis.expect(read.events.length).toBe(1);
225
- });
226
- };
227
- writeSkew("AdvisoryLocks", "dcb-skew-advisory");
228
- writeSkew("RowLocks", "dcb-skew-rows");
229
- globalThis.test("hot tag: N concurrent conditional appends, exactly one wins", async () => {
230
- let match = makeLog("dcb-hot");
231
- let ops = match[1];
232
- let cond_query = [{
233
- eventTypes: ["Claimed"],
234
- tags: [{
235
- key: "prizeId",
236
- value: "p1"
237
- }]
238
- }];
239
- let cond = {
240
- query: cond_query
241
- };
242
- let promises = Stdlib_Array.make(12, 0).map((param, i) => ops.append([stored("Claimed", [{
243
- key: "prizeId",
244
- value: "p1"
245
- }], Object.fromEntries([[
246
- "who",
247
- i
248
- ]]))], cond));
249
- let results = await Promise.all(promises);
250
- let oks = results.filter(r => r.TAG === "Ok").length;
251
- globalThis.expect(oks).toBe(1);
252
- let read = await ops.read([{
253
- tags: [{
254
- key: "prizeId",
255
- value: "p1"
256
- }]
257
- }], undefined);
258
- globalThis.expect(read.events.length).toBe(1);
259
- });
260
- globalThis.test("cursors are monotonic and usable as `after`", async () => {
261
- let match = makeLog("dcb-cursor");
262
- let ops = match[1];
263
- let mk = i => stored("Tick", [{
264
- key: "streamId",
265
- value: "c1"
266
- }], Object.fromEntries([[
267
- "i",
268
- i
269
- ]]));
270
- await ops.append([mk(0)], undefined);
271
- let pos = await ops.append([mk(1)], undefined);
272
- let mid;
273
- mid = pos.TAG === "Ok" ? pos._0 : "";
274
- await ops.append([mk(2)], undefined);
275
- let read = await ops.read([{
276
- tags: [{
277
- key: "streamId",
278
- value: "c1"
279
- }]
280
- }], mid);
281
- globalThis.expect(read.events.length).toBe(1);
282
- globalThis.expect(read.events[0].eventType).toBe("Tick");
283
- });
284
- });
285
- globalThis.describe("change feed", () => {
286
- globalThis.test("drains all events and checkpoints", async () => {
287
- let match = DcbEventLogStorage_Postgres$ReventlessPostgres.makeStorage(pool, "feed-log", [], {
288
- TAG: "Simple",
289
- _0: {
290
- key: "k"
291
- }
292
- }, undefined, opts, undefined, undefined);
293
- let mk = i => stored("Fed", [{
294
- key: "id",
295
- value: "f"
296
- }], Object.fromEntries([[
297
- "i",
298
- i
299
- ]]));
300
- await match[1].append([
301
- mk(0),
302
- mk(1),
303
- mk(2)
304
- ], undefined);
305
- let collected = {
306
- contents: 0
307
- };
308
- let processed = await PgChangeFeed$ReventlessPostgres.drain(pool, "feed-log", "sub-1", undefined, async evs => {
309
- collected.contents = collected.contents + evs.length | 0;
310
- });
311
- globalThis.expect(processed).toBe(3);
312
- globalThis.expect(collected.contents).toBe(3);
313
- let again = await PgChangeFeed$ReventlessPostgres.drain(pool, "feed-log", "sub-1", undefined, async param => {});
314
- globalThis.expect(again).toBe(0);
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
- });
365
- } else {
366
- globalThis.test("Postgres integration (skipped — set PG_URL to run)", () => {
367
- globalThis.expect(true).toBe(true);
368
- });
369
- }
370
-
371
- export {
372
- opts,
373
- jsonObj,
374
- stored,
375
- evJson,
376
- }
377
- /* url Not a pure module */