@awsless/dynamodb-server 0.1.1 → 0.1.3

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 (2) hide show
  1. package/dist/index.js +48 -28
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -251,6 +251,9 @@ function listTables(store, input) {
251
251
  };
252
252
  }
253
253
 
254
+ // src/expressions/condition.ts
255
+ import { cmp, parse } from "@awsless/big-float";
256
+
254
257
  // src/expressions/path.ts
255
258
  function parsePath(path, attributeNames) {
256
259
  const segments = [];
@@ -710,7 +713,7 @@ function evaluateCondition(expression, item, context) {
710
713
  if (!rightValue || !("N" in rightValue)) {
711
714
  throw new ValidationException("Size comparison requires numeric operand");
712
715
  }
713
- return compareNumbers(size, parseFloat(rightValue.N), nextToken.value);
716
+ return compareNumbers(size, Number(rightValue.N), nextToken.value);
714
717
  }
715
718
  return size > 0;
716
719
  }
@@ -778,20 +781,20 @@ function evaluateCondition(expression, item, context) {
778
781
  }
779
782
  return false;
780
783
  }
781
- const cmp = compareValues(left, right);
784
+ const cmp5 = compareValues(left, right);
782
785
  switch (op) {
783
786
  case "=":
784
- return cmp === 0;
787
+ return cmp5 === 0;
785
788
  case "<>":
786
- return cmp !== 0;
789
+ return cmp5 !== 0;
787
790
  case "<":
788
- return cmp < 0;
791
+ return cmp5 < 0;
789
792
  case "<=":
790
- return cmp <= 0;
793
+ return cmp5 <= 0;
791
794
  case ">":
792
- return cmp > 0;
795
+ return cmp5 > 0;
793
796
  case ">=":
794
- return cmp >= 0;
797
+ return cmp5 >= 0;
795
798
  default:
796
799
  return false;
797
800
  }
@@ -821,7 +824,7 @@ function compareValues(a, b) {
821
824
  return a.S.localeCompare(b.S);
822
825
  }
823
826
  if ("N" in a && "N" in b) {
824
- return parseFloat(a.N) - parseFloat(b.N);
827
+ return cmp(parse(a.N), parse(b.N));
825
828
  }
826
829
  if ("B" in a && "B" in b) {
827
830
  return a.B.localeCompare(b.B);
@@ -837,7 +840,11 @@ function compareValues(a, b) {
837
840
  return aStr.localeCompare(bStr);
838
841
  }
839
842
 
843
+ // src/expressions/key-condition.ts
844
+ import { cmp as cmp3, parse as parse3 } from "@awsless/big-float";
845
+
840
846
  // src/store/item.ts
847
+ import { cmp as cmp2, parse as parse2 } from "@awsless/big-float";
841
848
  function extractKey(item, keySchema) {
842
849
  const key = {};
843
850
  for (const element of keySchema) {
@@ -1009,21 +1016,21 @@ function matchesKeyCondition(item, condition) {
1009
1016
  return true;
1010
1017
  }
1011
1018
  function matchesRangeCondition(value, condition) {
1012
- const cmp = compareValues2(value, condition.value);
1019
+ const cmp5 = compareValues2(value, condition.value);
1013
1020
  switch (condition.operator) {
1014
1021
  case "=":
1015
- return cmp === 0;
1022
+ return cmp5 === 0;
1016
1023
  case "<":
1017
- return cmp < 0;
1024
+ return cmp5 < 0;
1018
1025
  case "<=":
1019
- return cmp <= 0;
1026
+ return cmp5 <= 0;
1020
1027
  case ">":
1021
- return cmp > 0;
1028
+ return cmp5 > 0;
1022
1029
  case ">=":
1023
- return cmp >= 0;
1030
+ return cmp5 >= 0;
1024
1031
  case "BETWEEN":
1025
1032
  if (!condition.value2) return false;
1026
- return cmp >= 0 && compareValues2(value, condition.value2) <= 0;
1033
+ return cmp5 >= 0 && compareValues2(value, condition.value2) <= 0;
1027
1034
  case "begins_with":
1028
1035
  if ("S" in value && "S" in condition.value) {
1029
1036
  return value.S.startsWith(condition.value.S);
@@ -1047,7 +1054,7 @@ function compareValues2(a, b) {
1047
1054
  return a.S.localeCompare(b.S);
1048
1055
  }
1049
1056
  if ("N" in a && "N" in b) {
1050
- return parseFloat(a.N) - parseFloat(b.N);
1057
+ return cmp3(parse3(a.N), parse3(b.N));
1051
1058
  }
1052
1059
  if ("B" in a && "B" in b) {
1053
1060
  return a.B.localeCompare(b.B);
@@ -1073,6 +1080,7 @@ function applyProjection(item, projectionExpression, expressionAttributeNames) {
1073
1080
  }
1074
1081
 
1075
1082
  // src/expressions/update.ts
1083
+ import { add, parse as parse4, string, sub } from "@awsless/big-float";
1076
1084
  function parseUpdateExpression(expression) {
1077
1085
  const actions = [];
1078
1086
  let remaining = expression.trim();
@@ -1266,6 +1274,20 @@ function resolveOperand(item, operand, context) {
1266
1274
  if (operand.startsWith(":")) {
1267
1275
  return context.expressionAttributeValues?.[operand];
1268
1276
  }
1277
+ const ifNotExistsMatch = operand.match(/^if_not_exists\s*\(\s*([^,]+)\s*,\s*(.+)\s*\)$/i);
1278
+ if (ifNotExistsMatch) {
1279
+ const existing = resolveOperand(item, ifNotExistsMatch[1].trim(), context);
1280
+ return existing !== void 0 ? existing : resolveOperand(item, ifNotExistsMatch[2].trim(), context);
1281
+ }
1282
+ const listAppendMatch = operand.match(/^list_append\s*\(\s*([^,]+)\s*,\s*(.+)\s*\)$/i);
1283
+ if (listAppendMatch) {
1284
+ const list1 = resolveOperand(item, listAppendMatch[1].trim(), context);
1285
+ const list2 = resolveOperand(item, listAppendMatch[2].trim(), context);
1286
+ if (list1 && "L" in list1 && list2 && "L" in list2) {
1287
+ return { L: [...list1.L, ...list2.L] };
1288
+ }
1289
+ return list1 && "L" in list1 ? list1 : list2;
1290
+ }
1269
1291
  const segments = parsePath(operand, context.expressionAttributeNames);
1270
1292
  return getValueAtPath(item, segments);
1271
1293
  }
@@ -1293,15 +1315,13 @@ function applySetAction(item, action, context) {
1293
1315
  const left = resolveOperand(item, action.operands[0], context);
1294
1316
  const right = resolveOperand(item, action.operands[1], context);
1295
1317
  if (left && "N" in left && right && "N" in right) {
1296
- const result = parseFloat(left.N) + parseFloat(right.N);
1297
- value = { N: String(result) };
1318
+ value = { N: string(add(parse4(left.N), parse4(right.N))) };
1298
1319
  }
1299
1320
  } else if (action.operation === "minus") {
1300
1321
  const left = resolveOperand(item, action.operands[0], context);
1301
1322
  const right = resolveOperand(item, action.operands[1], context);
1302
1323
  if (left && "N" in left && right && "N" in right) {
1303
- const result = parseFloat(left.N) - parseFloat(right.N);
1304
- value = { N: String(result) };
1324
+ value = { N: string(sub(parse4(left.N), parse4(right.N))) };
1305
1325
  }
1306
1326
  } else {
1307
1327
  value = resolveOperand(item, action.value, context);
@@ -1323,8 +1343,7 @@ function applyAddAction(item, action, context) {
1323
1343
  }
1324
1344
  if ("N" in addValue) {
1325
1345
  if (existingValue && "N" in existingValue) {
1326
- const result = parseFloat(existingValue.N) + parseFloat(addValue.N);
1327
- setValueAtPath(item, segments, { N: String(result) });
1346
+ setValueAtPath(item, segments, { N: string(add(parse4(existingValue.N), parse4(addValue.N))) });
1328
1347
  } else if (!existingValue) {
1329
1348
  setValueAtPath(item, segments, addValue);
1330
1349
  }
@@ -2299,6 +2318,7 @@ function createServer(store, port) {
2299
2318
  }
2300
2319
 
2301
2320
  // src/store/table.ts
2321
+ import { cmp as cmp4, parse as parse5 } from "@awsless/big-float";
2302
2322
  var sequenceCounter = 0;
2303
2323
  function generateSequenceNumber() {
2304
2324
  return String(++sequenceCounter).padStart(21, "0");
@@ -2618,8 +2638,8 @@ var Table = class {
2618
2638
  if (!aVal && !bVal) return 0;
2619
2639
  if (!aVal) return 1;
2620
2640
  if (!bVal) return -1;
2621
- const cmp = this.compareAttributes(aVal, bVal);
2622
- return options?.scanIndexForward === false ? -cmp : cmp;
2641
+ const cmp5 = this.compareAttributes(aVal, bVal);
2642
+ return options?.scanIndexForward === false ? -cmp5 : cmp5;
2623
2643
  });
2624
2644
  }
2625
2645
  let startIdx = 0;
@@ -2671,8 +2691,8 @@ var Table = class {
2671
2691
  if (!aVal && !bVal) return 0;
2672
2692
  if (!aVal) return 1;
2673
2693
  if (!bVal) return -1;
2674
- const cmp = this.compareAttributes(aVal, bVal);
2675
- return options?.scanIndexForward === false ? -cmp : cmp;
2694
+ const cmp5 = this.compareAttributes(aVal, bVal);
2695
+ return options?.scanIndexForward === false ? -cmp5 : cmp5;
2676
2696
  });
2677
2697
  }
2678
2698
  let startIdx = 0;
@@ -2775,7 +2795,7 @@ var Table = class {
2775
2795
  }
2776
2796
  compareAttributes(a, b) {
2777
2797
  if ("S" in a && "S" in b) return a.S.localeCompare(b.S);
2778
- if ("N" in a && "N" in b) return parseFloat(a.N) - parseFloat(b.N);
2798
+ if ("N" in a && "N" in b) return cmp4(parse5(a.N), parse5(b.N));
2779
2799
  if ("B" in a && "B" in b) return a.B.localeCompare(b.B);
2780
2800
  return 0;
2781
2801
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awsless/dynamodb-server",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -24,7 +24,8 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@aws-sdk/client-dynamodb": "3.363.0",
27
- "@aws-sdk/lib-dynamodb": "3.363.0"
27
+ "@aws-sdk/lib-dynamodb": "3.363.0",
28
+ "@awsless/big-float": "^0.1.5"
28
29
  },
29
30
  "optionalDependencies": {
30
31
  "dynamo-db-local": "^10.3.0"