qstd 0.2.27 → 0.3.0

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.
@@ -1,5 +1,7 @@
1
1
  import { format, formatDistanceToNow, formatISO, isSameYear, isSameMonth, isSameDay, addSeconds, addMinutes, addHours, addDays, addWeeks, addBusinessDays, addMonths, addYears } from 'date-fns';
2
2
  import { promises } from 'fs';
3
+ import { DynamoDBDocumentClient, ScanCommand, QueryCommand, DeleteCommand, PutCommand, BatchGetCommand, TransactWriteCommand, BatchWriteCommand } from '@aws-sdk/lib-dynamodb';
4
+ import { DynamoDBClient, DeleteTableCommand, DescribeTableCommand, DynamoDBServiceException } from '@aws-sdk/client-dynamodb';
3
5
 
4
6
  var __defProp = Object.defineProperty;
5
7
  var __export = (target, all) => {
@@ -259,6 +261,7 @@ __export(time_exports, {
259
261
  formatThreadDateRange: () => formatThreadDateRange,
260
262
  now: () => now,
261
263
  sleep: () => sleep,
264
+ startTimer: () => startTimer,
262
265
  toMs: () => toMs
263
266
  });
264
267
  var formatDuration = (ms, options = {}) => {
@@ -453,6 +456,27 @@ var toMs = (value, unit = "seconds") => {
453
456
  };
454
457
  return value * multipliers[unit];
455
458
  };
459
+ function startTimer(options = {}) {
460
+ const start = Date.now();
461
+ const fmt = options.format ?? "ms";
462
+ const getElapsed = () => {
463
+ const elapsed = Date.now() - start;
464
+ if (fmt === "compact") {
465
+ const hours = Math.floor(elapsed / 36e5);
466
+ const minutes = Math.floor(elapsed % 36e5 / 6e4);
467
+ const seconds = Math.floor(elapsed % 6e4 / 1e3);
468
+ const milliseconds = elapsed % 1e3;
469
+ let result = "";
470
+ if (hours > 0) result += `${hours}h`;
471
+ if (minutes > 0) result += `${minutes}m`;
472
+ if (seconds > 0) result += `${seconds}s`;
473
+ if (milliseconds > 0 || result === "") result += `${milliseconds}ms`;
474
+ return result;
475
+ }
476
+ return elapsed;
477
+ };
478
+ return { stop: getElapsed, elapsed: getElapsed };
479
+ }
456
480
 
457
481
  // src/shared/flow.ts
458
482
  var flow_exports = {};
@@ -550,14 +574,9 @@ __export(log_exports, {
550
574
  info: () => info,
551
575
  label: () => label,
552
576
  log: () => log,
553
- startTimer: () => startTimer,
554
577
  warn: () => warn
555
578
  });
556
579
  var stringify = (value) => JSON.stringify(value, null, 2);
557
- var startTimer = () => {
558
- const start = Date.now();
559
- return () => Date.now() - start;
560
- };
561
580
  var log = (...values) => {
562
581
  console.log(...values.map(stringify));
563
582
  };
@@ -605,8 +624,8 @@ var readFile = async (filePath, encoding = "utf-8") => {
605
624
  var writeBufferToFile = async (filepath, buffer) => {
606
625
  if (!buffer) return;
607
626
  const chunks = [];
608
- for await (const chunk2 of buffer) {
609
- chunks.push(chunk2);
627
+ for await (const chunk3 of buffer) {
628
+ chunks.push(chunk3);
610
629
  }
611
630
  await promises.writeFile(filepath, Buffer.concat(chunks));
612
631
  };
@@ -614,4 +633,600 @@ var writeFile = async (filepath, content) => {
614
633
  return promises.writeFile(filepath, content);
615
634
  };
616
635
 
617
- export { dict_exports as Dict, file_exports as File, flow_exports as Flow, int_exports as Int, list_exports as List, log_exports as Log, money_exports as Money, random_exports as Random, str_exports as Str, time_exports as Time };
636
+ // src/server/aws/ddb/index.ts
637
+ var ddb_exports = {};
638
+ __export(ddb_exports, {
639
+ batchDelete: () => batchDelete,
640
+ batchGet: () => batchGet,
641
+ batchWrite: () => batchWrite,
642
+ create: () => create2,
643
+ deleteTable: () => deleteTable,
644
+ find: () => find,
645
+ lsi: () => lsi,
646
+ lsi2: () => lsi2,
647
+ lsiNormalized: () => lsiNormalized,
648
+ lsiPhash: () => lsiPhash,
649
+ lsiUsername: () => lsiUsername,
650
+ remove: () => remove,
651
+ save: () => save,
652
+ tableExists: () => tableExists
653
+ });
654
+
655
+ // src/server/aws/ddb/fns.ts
656
+ var validateFindProps = (props) => {
657
+ const isScan = "scan" in props && props.scan === true;
658
+ if (!props.tableName) {
659
+ throw new Error(`[ddb] "tableName" is required`);
660
+ }
661
+ if (props.limit && props.recursive) {
662
+ throw new Error(`[ddb] "limit" and "recursive" cannot be used together`);
663
+ }
664
+ if (!isScan) {
665
+ const queryProps = props;
666
+ if (!queryProps.pk) {
667
+ throw new Error(`[ddb] [find] "pk" is required for Query mode. Use scan: true to scan without pk.`);
668
+ }
669
+ if (queryProps.sk && "key" in queryProps.sk && queryProps.sk.key && queryProps.sk.key !== "sk" && !queryProps.indexName) {
670
+ throw new Error(
671
+ `[ddb] [find] you provided a custom sk but no indexName. If this is a mistake, change this error to a warn.`
672
+ );
673
+ }
674
+ }
675
+ };
676
+ var buildKeyConditionExpression = (pk, sk, names, values) => {
677
+ const pkKey = pk.key ?? "pk";
678
+ names["#pk"] = pkKey;
679
+ values[":pk"] = pk.value;
680
+ if (!sk) return "#pk = :pk";
681
+ const skName = sk.key ?? "sk";
682
+ names["#sk"] = skName;
683
+ if ("op" in sk && sk.op) {
684
+ switch (sk.op) {
685
+ case "=":
686
+ case ">=":
687
+ case ">":
688
+ case "<=":
689
+ case "<":
690
+ values[":sk"] = sk.value;
691
+ return `#pk = :pk AND #sk ${sk.op} :sk`;
692
+ case "begins_with":
693
+ values[":sk"] = sk.value;
694
+ return `#pk = :pk AND begins_with(#sk, :sk)`;
695
+ case "between": {
696
+ const [from, to] = sk.value;
697
+ values[":skFrom"] = from;
698
+ values[":skTo"] = to;
699
+ return `#pk = :pk AND #sk BETWEEN :skFrom AND :skTo`;
700
+ }
701
+ default:
702
+ throw new Error(`Unsupported SK op: ${JSON.stringify(sk, null, 2)}`);
703
+ }
704
+ }
705
+ if ("value" in sk && sk.value !== void 0) {
706
+ values[":sk"] = sk.value;
707
+ return `#pk = :pk AND #sk = :sk`;
708
+ }
709
+ if ("valueBeginsWith" in sk && sk.valueBeginsWith !== void 0) {
710
+ values[":sk"] = sk.valueBeginsWith;
711
+ return `#pk = :pk AND begins_with(#sk, :sk)`;
712
+ }
713
+ throw new Error(
714
+ `Invalid SK condition: expected 'op' or legacy 'value'/'valueBeginsWith'`
715
+ );
716
+ };
717
+ var buildFilterExpression = (filters, names, values) => {
718
+ if (!filters || filters.length === 0) return void 0;
719
+ const frags = [];
720
+ filters.forEach((f, i) => {
721
+ const nameToken = `#f${i}`;
722
+ names[nameToken] = f.key;
723
+ switch (f.op) {
724
+ case "attribute_exists":
725
+ frags.push(`attribute_exists(${nameToken})`);
726
+ break;
727
+ case "attribute_not_exists":
728
+ frags.push(`attribute_not_exists(${nameToken})`);
729
+ break;
730
+ case "between": {
731
+ const [lo, hi] = f.value;
732
+ const loPh = `:f${i}_lo`;
733
+ const hiPh = `:f${i}_hi`;
734
+ values[loPh] = lo;
735
+ values[hiPh] = hi;
736
+ frags.push(`${nameToken} BETWEEN ${loPh} AND ${hiPh}`);
737
+ break;
738
+ }
739
+ case "in": {
740
+ const arr = f.value;
741
+ if (!arr.length) {
742
+ throw new Error(
743
+ `'in' filter for ${f.key} requires at least one value`
744
+ );
745
+ }
746
+ const phs = arr.map((_, j) => `:f${i}_${j}`);
747
+ arr.forEach((v, j) => {
748
+ const ph = phs[j];
749
+ if (ph) values[ph] = v;
750
+ });
751
+ frags.push(`${nameToken} IN (${phs.join(", ")})`);
752
+ break;
753
+ }
754
+ case "contains":
755
+ case "begins_with": {
756
+ const ph = `:f${i}`;
757
+ values[ph] = f.value;
758
+ frags.push(`${f.op}(${nameToken}, ${ph})`);
759
+ break;
760
+ }
761
+ case "=":
762
+ case "<>":
763
+ case ">":
764
+ case ">=":
765
+ case "<":
766
+ case "<=": {
767
+ const ph = `:f${i}`;
768
+ values[ph] = f.value;
769
+ frags.push(`${nameToken} ${f.op} ${ph}`);
770
+ break;
771
+ }
772
+ }
773
+ });
774
+ return frags.join(" AND ");
775
+ };
776
+ var buildProjectionExpression = (projection, names) => {
777
+ const projectionNames = projection.map((key, idx) => {
778
+ const nameKey = `#proj${idx}`;
779
+ names[nameKey] = key;
780
+ return nameKey;
781
+ });
782
+ return projectionNames.join(", ");
783
+ };
784
+ var sleep3 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
785
+ var backoffDelay = (attempt) => {
786
+ return Math.min(1e3 * Math.pow(2, attempt), 1e4);
787
+ };
788
+ var chunk2 = (arr, size) => {
789
+ return Array.from(
790
+ { length: Math.ceil(arr.length / size) },
791
+ (_, i) => arr.slice(i * size, i * size + size)
792
+ );
793
+ };
794
+
795
+ // src/server/aws/ddb/domain.ts
796
+ var create2 = (props) => {
797
+ const tableName = props?.tableName;
798
+ const credentials = props?.credentials;
799
+ const client = DynamoDBDocumentClient.from(
800
+ new DynamoDBClient({
801
+ ...credentials && { credentials },
802
+ region: "us-east-1"
803
+ }),
804
+ {
805
+ marshallOptions: {
806
+ // Whether to automatically convert empty strings, blobs, and sets to `null`.
807
+ convertEmptyValues: false,
808
+ // false, by default.
809
+ // Whether to remove undefined values while marshalling.
810
+ removeUndefinedValues: false,
811
+ // false, by default.
812
+ // Whether to convert typeof object to map attribute.
813
+ convertClassInstanceToMap: false
814
+ // false, by default.
815
+ },
816
+ unmarshallOptions: {
817
+ // Whether to return numbers as a string instead of converting them to native JavaScript numbers.
818
+ wrapNumbers: false
819
+ // false, by default.
820
+ }
821
+ }
822
+ );
823
+ return { client, tableName };
824
+ };
825
+ async function find(ddb, props) {
826
+ try {
827
+ const TableName = props.tableName ?? ddb.tableName;
828
+ const { filters, projection, debug } = props;
829
+ const isScan = "scan" in props && props.scan === true;
830
+ validateFindProps(props);
831
+ const names = {};
832
+ const values = {};
833
+ const KeyConditionExpression = isScan ? void 0 : buildKeyConditionExpression(
834
+ props.pk,
835
+ props.sk,
836
+ names,
837
+ values
838
+ );
839
+ const FilterExpression = filters ? buildFilterExpression(filters, names, values) : void 0;
840
+ if (debug) {
841
+ console.log(`[debug] [ddb] [find] input:`, {
842
+ isScan,
843
+ filters,
844
+ FilterExpression,
845
+ names,
846
+ values
847
+ });
848
+ }
849
+ const ProjectionExpression = projection ? buildProjectionExpression(projection, names) : void 0;
850
+ const all = [];
851
+ let startKey = props.startKey;
852
+ let pageCount = 0;
853
+ let totalItems = 0;
854
+ do {
855
+ if (props.maxPages && pageCount >= props.maxPages) break;
856
+ const command = isScan ? new ScanCommand({
857
+ TableName,
858
+ IndexName: props.indexName,
859
+ FilterExpression,
860
+ Limit: props.limit,
861
+ ProjectionExpression,
862
+ ExclusiveStartKey: startKey,
863
+ ConsistentRead: props.strong,
864
+ ...Object.keys(names).length > 0 && {
865
+ ExpressionAttributeNames: names
866
+ },
867
+ ...Object.keys(values).length > 0 && {
868
+ ExpressionAttributeValues: values
869
+ }
870
+ }) : new QueryCommand({
871
+ TableName,
872
+ IndexName: props.indexName,
873
+ KeyConditionExpression,
874
+ FilterExpression,
875
+ Limit: props.limit,
876
+ ProjectionExpression,
877
+ ExclusiveStartKey: startKey,
878
+ ConsistentRead: props.strong,
879
+ ExpressionAttributeNames: names,
880
+ ExpressionAttributeValues: values,
881
+ ScanIndexForward: props.sort === "desc" ? false : true
882
+ });
883
+ const result = await ddb.client.send(command);
884
+ const pageItems = result.Items ?? [];
885
+ all.push(...pageItems);
886
+ totalItems += pageItems.length;
887
+ pageCount++;
888
+ startKey = result.LastEvaluatedKey;
889
+ if (props.recursive) {
890
+ if (props.maxItems && totalItems >= props.maxItems) break;
891
+ if (!startKey) break;
892
+ if (typeof props.recursive === "function") {
893
+ const page = {
894
+ lastEvaluatedKey: result.LastEvaluatedKey,
895
+ scannedCount: result.ScannedCount ?? 0,
896
+ count: result.Count ?? 0,
897
+ items: pageItems
898
+ };
899
+ const shouldContinue = props.recursive(page, pageCount, totalItems);
900
+ if (!shouldContinue) break;
901
+ }
902
+ } else {
903
+ break;
904
+ }
905
+ } while (true);
906
+ const rawResponse = {
907
+ lastEvaluatedKey: startKey,
908
+ scannedCount: totalItems,
909
+ count: totalItems,
910
+ items: all
911
+ };
912
+ if (props.raw && props.first) {
913
+ return {
914
+ count: rawResponse.count,
915
+ item: rawResponse.items[0],
916
+ scannedCount: rawResponse.scannedCount
917
+ };
918
+ }
919
+ if (props.raw) return rawResponse;
920
+ if (props.first) return rawResponse.items[0];
921
+ return rawResponse.items;
922
+ } catch (error2) {
923
+ const err = error2;
924
+ console.log(`[error] [ddb] [find] failed with ${err.message}. Input:`);
925
+ console.dir(props, { depth: 100 });
926
+ throw err;
927
+ }
928
+ }
929
+ var remove = async (ddb, props) => {
930
+ const TableName = props.tableName ?? ddb.tableName;
931
+ const command = new DeleteCommand({ Key: props.key, TableName });
932
+ return ddb.client.send(command);
933
+ };
934
+ var save = async (ddb, props) => {
935
+ const TableName = props.tableName ?? ddb.tableName;
936
+ const command = new PutCommand({
937
+ Item: props.item,
938
+ TableName
939
+ });
940
+ return ddb.client.send(command);
941
+ };
942
+ async function batchGet(ddb, props) {
943
+ const { keys, maxRetries = 3, strong = false } = props;
944
+ const TableName = props.tableName ?? ddb.tableName;
945
+ const chunks = chunk2(keys, 100);
946
+ const allItems = [];
947
+ const requestedCount = keys.length;
948
+ let totalConsumedCapacity = 0;
949
+ for (const chunk3 of chunks) {
950
+ let attempt = 0;
951
+ let keysToFetch = chunk3;
952
+ while (keysToFetch.length > 0 && attempt <= maxRetries) {
953
+ if (attempt > 0) {
954
+ const delay = backoffDelay(attempt);
955
+ console.log(
956
+ `[info] [ddb] [batchGet]: Retrying ${keysToFetch.length} keys (attempt ${attempt}/${maxRetries}) after ${delay}ms`
957
+ );
958
+ await sleep3(delay);
959
+ }
960
+ try {
961
+ const command = new BatchGetCommand({
962
+ RequestItems: {
963
+ [TableName]: { Keys: keysToFetch, ConsistentRead: strong }
964
+ }
965
+ });
966
+ const result = await ddb.client.send(command);
967
+ const items = result.Responses?.[TableName] ?? [];
968
+ allItems.push(...items);
969
+ if (result.ConsumedCapacity) {
970
+ totalConsumedCapacity += result.ConsumedCapacity.reduce(
971
+ (sum, cap) => sum + (cap.CapacityUnits ?? 0),
972
+ 0
973
+ );
974
+ }
975
+ const unprocessed = result.UnprocessedKeys?.[TableName]?.Keys;
976
+ if (unprocessed && unprocessed.length > 0) {
977
+ keysToFetch = unprocessed;
978
+ attempt++;
979
+ } else {
980
+ keysToFetch = [];
981
+ }
982
+ } catch (error2) {
983
+ console.log(
984
+ `[error] [ddb] [batchGet]: Error fetching chunk (attempt ${attempt}/${maxRetries}):`,
985
+ error2
986
+ );
987
+ if (attempt >= maxRetries) throw error2;
988
+ attempt++;
989
+ }
990
+ }
991
+ if (keysToFetch.length > 0) {
992
+ console.log(
993
+ `[error] [ddb] [batchGet]: Failed to fetch ${keysToFetch.length} keys after ${maxRetries} retries`
994
+ );
995
+ }
996
+ }
997
+ const missing = requestedCount - allItems.length;
998
+ return {
999
+ missing,
1000
+ items: allItems,
1001
+ count: allItems.length,
1002
+ consumedCapacity: totalConsumedCapacity || void 0
1003
+ };
1004
+ }
1005
+ async function batchWrite(ddb, props) {
1006
+ const { maxRetries = 3 } = props;
1007
+ const TableName = props.tableName ?? ddb.tableName;
1008
+ const items = props.transform ? props.items.map(props.transform) : props.items;
1009
+ const hasConditions = items.some((x) => x.cond);
1010
+ const chunkSize = hasConditions ? 100 : 25;
1011
+ const chunks = chunk2(items, chunkSize);
1012
+ let processedCount = 0;
1013
+ let failedCount = 0;
1014
+ let totalConsumedCapacity = 0;
1015
+ for (const chunk3 of chunks) {
1016
+ let attempt = 0;
1017
+ let itemsToWrite = chunk3;
1018
+ while (itemsToWrite.length > 0 && attempt <= maxRetries) {
1019
+ if (attempt > 0) {
1020
+ const delay = backoffDelay(attempt);
1021
+ console.log(
1022
+ `[info] [ddb] [batchWrite]: Retrying ${itemsToWrite.length} items (attempt ${attempt}/${maxRetries}) after ${delay}ms`
1023
+ );
1024
+ await sleep3(delay);
1025
+ }
1026
+ try {
1027
+ if (hasConditions) {
1028
+ const transactItems = itemsToWrite.map((x) => ({
1029
+ Put: {
1030
+ TableName,
1031
+ Item: x.item,
1032
+ ...x.cond && { ConditionExpression: x.cond }
1033
+ }
1034
+ }));
1035
+ const command = new TransactWriteCommand({
1036
+ TransactItems: transactItems
1037
+ });
1038
+ const result = await ddb.client.send(command);
1039
+ if (result.ConsumedCapacity) {
1040
+ totalConsumedCapacity += result.ConsumedCapacity.reduce(
1041
+ (sum, cap) => sum + (cap.CapacityUnits ?? 0),
1042
+ 0
1043
+ );
1044
+ }
1045
+ processedCount += itemsToWrite.length;
1046
+ itemsToWrite = [];
1047
+ } else {
1048
+ const writeRequests = itemsToWrite.map((x) => ({
1049
+ PutRequest: { Item: x.item }
1050
+ }));
1051
+ const command = new BatchWriteCommand({
1052
+ RequestItems: { [TableName]: writeRequests }
1053
+ });
1054
+ const result = await ddb.client.send(command);
1055
+ if (result.ConsumedCapacity) {
1056
+ totalConsumedCapacity += result.ConsumedCapacity.reduce(
1057
+ (sum, cap) => sum + (cap.CapacityUnits ?? 0),
1058
+ 0
1059
+ );
1060
+ }
1061
+ const unprocessed = result.UnprocessedItems?.[TableName];
1062
+ if (unprocessed && unprocessed.length > 0) {
1063
+ itemsToWrite = unprocessed.map((req) => ({
1064
+ item: req.PutRequest.Item
1065
+ }));
1066
+ processedCount += chunk3.length - itemsToWrite.length;
1067
+ attempt++;
1068
+ } else {
1069
+ processedCount += itemsToWrite.length;
1070
+ itemsToWrite = [];
1071
+ }
1072
+ }
1073
+ } catch (error2) {
1074
+ console.log(
1075
+ `[error] [ddb] [batchWrite]: Error writing chunk (attempt ${attempt}/${maxRetries}):`,
1076
+ error2
1077
+ );
1078
+ if (attempt >= maxRetries) {
1079
+ failedCount += itemsToWrite.length;
1080
+ itemsToWrite = [];
1081
+ } else {
1082
+ attempt++;
1083
+ }
1084
+ }
1085
+ }
1086
+ if (itemsToWrite.length > 0) {
1087
+ console.log(
1088
+ `[error] [ddb] [batchWrite]: Failed to write ${itemsToWrite.length} items after ${maxRetries} retries`
1089
+ );
1090
+ failedCount += itemsToWrite.length;
1091
+ }
1092
+ }
1093
+ return {
1094
+ failed: failedCount,
1095
+ processed: processedCount,
1096
+ consumedCapacity: totalConsumedCapacity || void 0
1097
+ };
1098
+ }
1099
+ async function batchDelete(ddb, props) {
1100
+ const { maxRetries = 3 } = props;
1101
+ const TableName = props.tableName ?? ddb.tableName;
1102
+ const keys = props.transform ? props.keys.map(props.transform) : props.keys;
1103
+ const hasConditions = keys.some((x) => x.cond);
1104
+ const chunkSize = hasConditions ? 100 : 25;
1105
+ const chunks = chunk2(keys, chunkSize);
1106
+ let processedCount = 0;
1107
+ let failedCount = 0;
1108
+ let totalConsumedCapacity = 0;
1109
+ for (const chunk3 of chunks) {
1110
+ let attempt = 0;
1111
+ let itemsToDelete = chunk3;
1112
+ while (itemsToDelete.length > 0 && attempt <= maxRetries) {
1113
+ if (attempt > 0) {
1114
+ const delay = backoffDelay(attempt);
1115
+ console.log(
1116
+ `[info] [ddb] [batchDelete]: Retrying ${itemsToDelete.length} items (attempt ${attempt}/${maxRetries}) after ${delay}ms`
1117
+ );
1118
+ await sleep3(delay);
1119
+ }
1120
+ try {
1121
+ if (hasConditions) {
1122
+ const transactItems = itemsToDelete.map((x) => ({
1123
+ Delete: {
1124
+ TableName,
1125
+ Key: x.key,
1126
+ ...x.cond && { ConditionExpression: x.cond }
1127
+ }
1128
+ }));
1129
+ const command = new TransactWriteCommand({
1130
+ TransactItems: transactItems
1131
+ });
1132
+ const result = await ddb.client.send(command);
1133
+ if (result.ConsumedCapacity) {
1134
+ totalConsumedCapacity += result.ConsumedCapacity.reduce(
1135
+ (sum, cap) => sum + (cap.CapacityUnits ?? 0),
1136
+ 0
1137
+ );
1138
+ }
1139
+ processedCount += itemsToDelete.length;
1140
+ itemsToDelete = [];
1141
+ } else {
1142
+ const writeRequests = itemsToDelete.map((x) => ({
1143
+ DeleteRequest: { Key: x.key }
1144
+ }));
1145
+ const command = new BatchWriteCommand({
1146
+ RequestItems: { [TableName]: writeRequests }
1147
+ });
1148
+ const result = await ddb.client.send(command);
1149
+ if (result.ConsumedCapacity) {
1150
+ totalConsumedCapacity += result.ConsumedCapacity.reduce(
1151
+ (sum, cap) => sum + (cap.CapacityUnits ?? 0),
1152
+ 0
1153
+ );
1154
+ }
1155
+ const unprocessed = result.UnprocessedItems?.[TableName];
1156
+ if (unprocessed && unprocessed.length > 0) {
1157
+ itemsToDelete = unprocessed.map((req) => ({
1158
+ key: req.DeleteRequest.Key
1159
+ }));
1160
+ processedCount += chunk3.length - itemsToDelete.length;
1161
+ attempt++;
1162
+ } else {
1163
+ processedCount += itemsToDelete.length;
1164
+ itemsToDelete = [];
1165
+ }
1166
+ }
1167
+ } catch (error2) {
1168
+ console.log(
1169
+ `[error] [ddb] [batchDelete]: Error deleting chunk (attempt ${attempt}/${maxRetries}):`,
1170
+ error2
1171
+ );
1172
+ if (attempt >= maxRetries) {
1173
+ failedCount += itemsToDelete.length;
1174
+ itemsToDelete = [];
1175
+ } else {
1176
+ attempt++;
1177
+ }
1178
+ }
1179
+ }
1180
+ if (itemsToDelete.length > 0) {
1181
+ console.log(
1182
+ `[error] [ddb] [batchDelete]: Failed to delete ${itemsToDelete.length} items after ${maxRetries} retries`
1183
+ );
1184
+ failedCount += itemsToDelete.length;
1185
+ }
1186
+ }
1187
+ return {
1188
+ failed: failedCount,
1189
+ processed: processedCount,
1190
+ consumedCapacity: totalConsumedCapacity || void 0
1191
+ };
1192
+ }
1193
+ var deleteTable = (ddb, tableName) => {
1194
+ const TableName = tableName;
1195
+ const command = new DeleteTableCommand({ TableName });
1196
+ return ddb.client.send(command);
1197
+ };
1198
+ var tableExists = async (ddb, props) => {
1199
+ try {
1200
+ const TableName = props.tableName;
1201
+ const command = new DescribeTableCommand({ TableName });
1202
+ await ddb.client.send(command);
1203
+ return true;
1204
+ } catch (err) {
1205
+ if (err instanceof DynamoDBServiceException) {
1206
+ if (err.name === "ResourceNotFoundException" || err.$metadata.httpStatusCode === 400) {
1207
+ return false;
1208
+ }
1209
+ }
1210
+ throw err;
1211
+ }
1212
+ };
1213
+
1214
+ // src/server/aws/ddb/literals.ts
1215
+ var lsi = { name: "lsi", sk: "lsi" };
1216
+ var lsi2 = { name: "lsi2", sk: "lsi2" };
1217
+ var lsiUsername = {
1218
+ name: "username-lsi",
1219
+ sk: "username"
1220
+ };
1221
+ var lsiNormalized = {
1222
+ /** use in index_name */
1223
+ name: "normalized-lsi",
1224
+ sk: "normalized"
1225
+ };
1226
+ var lsiPhash = {
1227
+ /** use in index_name */
1228
+ name: "phash-lsi",
1229
+ sk: "phash"
1230
+ };
1231
+
1232
+ export { ddb_exports as DDB, dict_exports as Dict, file_exports as File, flow_exports as Flow, int_exports as Int, list_exports as List, log_exports as Log, money_exports as Money, random_exports as Random, str_exports as Str, time_exports as Time };
@@ -17,16 +17,6 @@
17
17
  * log.header("HANDLER START"); // [audio-processor] ========== HANDLER START ==========
18
18
  *
19
19
  */
20
- /**
21
- * Starts a timer and returns a function that returns elapsed milliseconds.
22
- * @returns A function that returns the elapsed time in ms since the timer started
23
- * @example
24
- * ```typescript // Timer
25
- * const elapsed = Log.startTimer();
26
- * // ... do work ...
27
- * log.header(`COMPLETE (${elapsed()}ms)`); // ========== COMPLETE (123ms) ==========```
28
- */
29
- export declare const startTimer: () => () => number;
30
20
  /**
31
21
  * Logs values to the console (no prefix).
32
22
  * @param values - Values to log (will be JSON stringified)
@@ -1 +1 @@
1
- {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/shared/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,oBAWtB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,GAAI,GAAG,QAAQ,OAAO,EAAE,SAEvC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,GAAI,GAAG,QAAQ,OAAO,EAAE,SAExC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,GAAI,GAAG,QAAQ,OAAO,EAAE,SAExC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,GAAI,GAAG,QAAQ,OAAO,EAAE,SAEzC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,GAAI,SAAS,MAAM,SAErC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,KAAK,GAAI,MAAM,MAAM;IAChC,iEAAiE;sBAC/C,OAAO,EAAE;IAG3B,+EAA+E;sBAC7D,OAAO,EAAE;IAG3B,iFAAiF;uBAC9D,OAAO,EAAE;IAG5B,iGAAiG;sBAC/E,MAAM;CAGxB,CAAC"}
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/shared/log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,GAAI,GAAG,QAAQ,OAAO,EAAE,SAEvC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,GAAI,GAAG,QAAQ,OAAO,EAAE,SAExC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,GAAI,GAAG,QAAQ,OAAO,EAAE,SAExC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,GAAI,GAAG,QAAQ,OAAO,EAAE,SAEzC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,GAAI,SAAS,MAAM,SAErC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,KAAK,GAAI,MAAM,MAAM;IAChC,iEAAiE;sBAC/C,OAAO,EAAE;IAG3B,+EAA+E;sBAC7D,OAAO,EAAE;IAG3B,iFAAiF;uBAC9D,OAAO,EAAE;IAG5B,iGAAiG;sBAC/E,MAAM;CAGxB,CAAC"}