@farukada/aws-langgraph-dynamodb-ts 0.7.0 → 0.8.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.
- package/README.md +52 -9
- package/dist/checkpointer/actions/delete-thread.d.ts +3 -4
- package/dist/checkpointer/actions/delete-thread.d.ts.map +1 -1
- package/dist/checkpointer/actions/delete-thread.js +21 -41
- package/dist/checkpointer/actions/delete-thread.js.map +1 -1
- package/dist/checkpointer/actions/list.d.ts.map +1 -1
- package/dist/checkpointer/actions/list.js +31 -4
- package/dist/checkpointer/actions/list.js.map +1 -1
- package/dist/checkpointer/actions/put-writes.d.ts.map +1 -1
- package/dist/checkpointer/actions/put-writes.js +14 -24
- package/dist/checkpointer/actions/put-writes.js.map +1 -1
- package/dist/checkpointer/internal/item-reader.d.ts +31 -0
- package/dist/checkpointer/internal/item-reader.d.ts.map +1 -1
- package/dist/checkpointer/internal/item-reader.js +49 -1
- package/dist/checkpointer/internal/item-reader.js.map +1 -1
- package/dist/checkpointer/internal/item-writer.d.ts +0 -8
- package/dist/checkpointer/internal/item-writer.d.ts.map +1 -1
- package/dist/checkpointer/internal/item-writer.js +15 -21
- package/dist/checkpointer/internal/item-writer.js.map +1 -1
- package/dist/checkpointer/internal/keys.d.ts +19 -3
- package/dist/checkpointer/internal/keys.d.ts.map +1 -1
- package/dist/checkpointer/internal/keys.js +41 -6
- package/dist/checkpointer/internal/keys.js.map +1 -1
- package/dist/checkpointer/internal/validation.d.ts +8 -4
- package/dist/checkpointer/internal/validation.d.ts.map +1 -1
- package/dist/checkpointer/internal/validation.js +12 -10
- package/dist/checkpointer/internal/validation.js.map +1 -1
- package/dist/checkpointer/internal/write-guard.d.ts +21 -0
- package/dist/checkpointer/internal/write-guard.d.ts.map +1 -0
- package/dist/checkpointer/internal/write-guard.js +48 -0
- package/dist/checkpointer/internal/write-guard.js.map +1 -0
- package/dist/checkpointer/internal/write-index.d.ts +29 -0
- package/dist/checkpointer/internal/write-index.d.ts.map +1 -0
- package/dist/checkpointer/internal/write-index.js +38 -0
- package/dist/checkpointer/internal/write-index.js.map +1 -0
- package/dist/checkpointer/types.d.ts +2 -0
- package/dist/checkpointer/types.d.ts.map +1 -1
- package/dist/history/actions/add-messages.d.ts.map +1 -1
- package/dist/history/actions/add-messages.js +24 -4
- package/dist/history/actions/add-messages.js.map +1 -1
- package/dist/history/actions/clear.d.ts +4 -6
- package/dist/history/actions/clear.d.ts.map +1 -1
- package/dist/history/actions/clear.js +18 -33
- package/dist/history/actions/clear.js.map +1 -1
- package/dist/history/actions/get-messages.d.ts +2 -1
- package/dist/history/actions/get-messages.d.ts.map +1 -1
- package/dist/history/actions/get-messages.js +28 -2
- package/dist/history/actions/get-messages.js.map +1 -1
- package/dist/history/actions/list-sessions.d.ts +2 -1
- package/dist/history/actions/list-sessions.d.ts.map +1 -1
- package/dist/history/actions/list-sessions.js +21 -2
- package/dist/history/actions/list-sessions.js.map +1 -1
- package/dist/history/actions/reconcile-count.d.ts.map +1 -1
- package/dist/history/actions/reconcile-count.js +2 -2
- package/dist/history/actions/reconcile-count.js.map +1 -1
- package/dist/history/internal/append-saga.d.ts.map +1 -1
- package/dist/history/internal/append-saga.js +2 -78
- package/dist/history/internal/append-saga.js.map +1 -1
- package/dist/history/internal/compensation.d.ts +21 -0
- package/dist/history/internal/compensation.d.ts.map +1 -0
- package/dist/history/internal/compensation.js +84 -0
- package/dist/history/internal/compensation.js.map +1 -0
- package/dist/history/internal/keys.d.ts +9 -1
- package/dist/history/internal/keys.d.ts.map +1 -1
- package/dist/history/internal/keys.js +21 -4
- package/dist/history/internal/keys.js.map +1 -1
- package/dist/history/internal/message-chunker.d.ts.map +1 -1
- package/dist/history/internal/message-chunker.js +13 -5
- package/dist/history/internal/message-chunker.js.map +1 -1
- package/dist/history/internal/session-count.d.ts +21 -0
- package/dist/history/internal/session-count.d.ts.map +1 -1
- package/dist/history/internal/session-count.js +51 -0
- package/dist/history/internal/session-count.js.map +1 -1
- package/dist/history/internal/session-title.d.ts +20 -0
- package/dist/history/internal/session-title.d.ts.map +1 -0
- package/dist/history/internal/session-title.js +44 -0
- package/dist/history/internal/session-title.js.map +1 -0
- package/dist/history/internal/setup.d.ts +2 -1
- package/dist/history/internal/setup.d.ts.map +1 -1
- package/dist/history/internal/setup.js +1 -0
- package/dist/history/internal/setup.js.map +1 -1
- package/dist/history/internal/title-generator.d.ts +8 -2
- package/dist/history/internal/title-generator.d.ts.map +1 -1
- package/dist/history/internal/title-generator.js +12 -3
- package/dist/history/internal/title-generator.js.map +1 -1
- package/dist/history/internal/validation.d.ts +9 -0
- package/dist/history/internal/validation.d.ts.map +1 -0
- package/dist/history/internal/validation.js +16 -0
- package/dist/history/internal/validation.js.map +1 -0
- package/dist/history/types.d.ts +12 -0
- package/dist/history/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/shared/codec/s3/offloader.d.ts +7 -1
- package/dist/shared/codec/s3/offloader.d.ts.map +1 -1
- package/dist/shared/codec/s3/offloader.js +14 -1
- package/dist/shared/codec/s3/offloader.js.map +1 -1
- package/dist/shared/dynamodb/partition-delete.d.ts +33 -0
- package/dist/shared/dynamodb/partition-delete.d.ts.map +1 -0
- package/dist/shared/dynamodb/partition-delete.js +70 -0
- package/dist/shared/dynamodb/partition-delete.js.map +1 -0
- package/dist/shared/dynamodb/retry-classifier.d.ts.map +1 -1
- package/dist/shared/dynamodb/retry-classifier.js +9 -1
- package/dist/shared/dynamodb/retry-classifier.js.map +1 -1
- package/dist/shared/logging/redaction-walk.d.ts +23 -0
- package/dist/shared/logging/redaction-walk.d.ts.map +1 -0
- package/dist/shared/logging/redaction-walk.js +92 -0
- package/dist/shared/logging/redaction-walk.js.map +1 -0
- package/dist/shared/logging/redaction.d.ts +22 -17
- package/dist/shared/logging/redaction.d.ts.map +1 -1
- package/dist/shared/logging/redaction.js +24 -48
- package/dist/shared/logging/redaction.js.map +1 -1
- package/dist/shared/logging/secret-patterns.d.ts +41 -0
- package/dist/shared/logging/secret-patterns.d.ts.map +1 -0
- package/dist/shared/logging/secret-patterns.js +74 -0
- package/dist/shared/logging/secret-patterns.js.map +1 -0
- package/dist/shared/validation/primitives.d.ts +9 -1
- package/dist/shared/validation/primitives.d.ts.map +1 -1
- package/dist/shared/validation/primitives.js +13 -0
- package/dist/shared/validation/primitives.js.map +1 -1
- package/dist/store/actions/get.d.ts.map +1 -1
- package/dist/store/actions/get.js +15 -1
- package/dist/store/actions/get.js.map +1 -1
- package/dist/store/actions/list-namespaces.d.ts.map +1 -1
- package/dist/store/actions/list-namespaces.js +1 -0
- package/dist/store/actions/list-namespaces.js.map +1 -1
- package/dist/store/actions/put.d.ts.map +1 -1
- package/dist/store/actions/put.js +20 -2
- package/dist/store/actions/put.js.map +1 -1
- package/dist/store/actions/search.d.ts.map +1 -1
- package/dist/store/actions/search.js +4 -35
- package/dist/store/actions/search.js.map +1 -1
- package/dist/store/internal/backend-search.d.ts +5 -0
- package/dist/store/internal/backend-search.d.ts.map +1 -0
- package/dist/store/internal/backend-search.js +67 -0
- package/dist/store/internal/backend-search.js.map +1 -0
- package/dist/store/internal/filter.d.ts.map +1 -1
- package/dist/store/internal/filter.js +26 -5
- package/dist/store/internal/filter.js.map +1 -1
- package/dist/store/internal/index-reconcile.d.ts.map +1 -1
- package/dist/store/internal/index-reconcile.js +33 -3
- package/dist/store/internal/index-reconcile.js.map +1 -1
- package/dist/store/internal/keys.d.ts +1 -1
- package/dist/store/internal/keys.d.ts.map +1 -1
- package/dist/store/internal/keys.js +8 -2
- package/dist/store/internal/keys.js.map +1 -1
- package/dist/store/internal/persist.d.ts.map +1 -1
- package/dist/store/internal/persist.js +1 -5
- package/dist/store/internal/persist.js.map +1 -1
- package/dist/store/internal/search-filter.d.ts +4 -0
- package/dist/store/internal/search-filter.d.ts.map +1 -0
- package/dist/store/internal/search-filter.js +11 -0
- package/dist/store/internal/search-filter.js.map +1 -0
- package/dist/store/internal/setup.d.ts +11 -1
- package/dist/store/internal/setup.d.ts.map +1 -1
- package/dist/store/internal/setup.js +17 -1
- package/dist/store/internal/setup.js.map +1 -1
- package/dist/store/internal/validation.d.ts +8 -2
- package/dist/store/internal/validation.d.ts.map +1 -1
- package/dist/store/internal/validation.js +15 -6
- package/dist/store/internal/validation.js.map +1 -1
- package/dist/store/internal/write-verify.d.ts +12 -0
- package/dist/store/internal/write-verify.d.ts.map +1 -1
- package/dist/store/internal/write-verify.js +27 -0
- package/dist/store/internal/write-verify.js.map +1 -1
- package/dist/store/vector-backend.d.ts +17 -0
- package/dist/store/vector-backend.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -13,6 +13,7 @@ const keys_1 = require("../internal/keys");
|
|
|
13
13
|
const persist_1 = require("../internal/persist");
|
|
14
14
|
const semantic_search_1 = require("../internal/semantic-search");
|
|
15
15
|
const validation_1 = require("../internal/validation");
|
|
16
|
+
const write_verify_1 = require("../internal/write-verify");
|
|
16
17
|
async function readExisting(context, pk, sk) {
|
|
17
18
|
const existing = await (0, retry_1.withDynamoDBRetry)(() => context.client.get({
|
|
18
19
|
TableName: context.tableName,
|
|
@@ -26,10 +27,27 @@ async function readExisting(context, pk, sk) {
|
|
|
26
27
|
value: existing.Item?.value,
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Delete the item and, when a vector backend is configured, drop its vector.
|
|
32
|
+
*
|
|
33
|
+
* A retry-exhausted failure is *ambiguous*: the delete may have landed
|
|
34
|
+
* server-side with only its acknowledgement lost. Mirroring `persistRecord`'s
|
|
35
|
+
* treatment of an ambiguous put, that case is resolved with a
|
|
36
|
+
* strongly-consistent read — if the row is genuinely gone the delete
|
|
37
|
+
* succeeded, so the S3-orphan cleanup and the vector-backend delete must still
|
|
38
|
+
* run rather than being skipped for a write that actually happened. Any other
|
|
39
|
+
* failure, or a row still present, propagates unchanged.
|
|
40
|
+
*/
|
|
30
41
|
async function deleteStoreItem(context, op, pk, sk) {
|
|
31
42
|
const existing = context.offloader ? await readExisting(context, pk, sk) : undefined;
|
|
32
|
-
|
|
43
|
+
try {
|
|
44
|
+
await (0, retry_1.withDynamoDBRetry)(() => context.client.delete({ TableName: context.tableName, Key: { PK: pk, SK: sk } }));
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const landed = (0, write_verify_1.isRetryExhausted)(error) && (await (0, write_verify_1.rowIsAbsent)(context, { PK: pk, SK: sk }));
|
|
48
|
+
if (!landed)
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
33
51
|
if (context.offloader) {
|
|
34
52
|
await (0, orphans_1.cleanUpS3Orphans)(context.offloader, (0, descriptor_keys_1.collectS3Keys)(existing?.value ? [existing.value] : []), 'store.delete', context.logger);
|
|
35
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"put.js","sourceRoot":"","sources":["../../../src/store/actions/put.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AAIzC,8CAA4C;AAE5C,wEAAmE;AACnE,2DAAiE;AACjE,uDAAgE;AAChE,qDAAoE;AAEpE,uDAAyD;AACzD,yDAAyD;AACzD,2CAAyD;AACzD,iDAAoD;AACpD,iEAAyD;AAEzD,uDAAwE;
|
|
1
|
+
{"version":3,"file":"put.js","sourceRoot":"","sources":["../../../src/store/actions/put.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AAIzC,8CAA4C;AAE5C,wEAAmE;AACnE,2DAAiE;AACjE,uDAAgE;AAChE,qDAAoE;AAEpE,uDAAyD;AACzD,yDAAyD;AACzD,2CAAyD;AACzD,iDAAoD;AACpD,iEAAyD;AAEzD,uDAAwE;AACxE,2DAAyE;AAQzE,KAAK,UAAU,YAAY,CACzB,OAAqB,EACrB,EAAU,EACV,EAAU;IAEV,MAAM,QAAQ,GAAG,MAAM,IAAA,yBAAiB,EAAC,GAAG,EAAE,CAC5C,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC;QACjB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;QACvB,cAAc,EAAE,IAAI;QACpB,oBAAoB,EAAE,QAAQ;QAC9B,wBAAwB,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE;KAC/D,CAAC,CACH,CAAC;IACF,OAAO;QACL,SAAS,EAAE,QAAQ,CAAC,IAAI,EAAE,SAA+B;QACzD,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,KAAsC;KAC7D,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,KAAK,UAAU,eAAe,CAC5B,OAAqB,EACrB,EAAgB,EAChB,EAAU,EACV,EAAU;IAEV,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,IAAI,CAAC;QACH,MAAM,IAAA,yBAAiB,EAAC,GAAG,EAAE,CAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CACjF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GACV,IAAA,+BAAgB,EAAC,KAAc,CAAC,IAAI,CAAC,MAAM,IAAA,0BAAW,EAAC,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACvF,IAAI,CAAC,MAAM;YAAE,MAAM,KAAK,CAAC;IAC3B,CAAC;IACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,IAAA,0BAAgB,EACpB,OAAO,CAAC,SAAS,EACjB,IAAA,+BAAa,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EACtD,cAAc,EACd,OAAO,CAAC,MAAM,CACf,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,IAAA,4BAAe,EAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAChG,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,KAAK,UAAU,gBAAgB,CAC7B,OAAqB,EACrB,EAAgB,EAChB,KAAgC;IAEhC,IAAI,EAAE,CAAC,KAAK,KAAK,KAAK;QAAE,OAAO,SAAS,CAAC;IACzC,OAAO,IAAA,4BAAU,EAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AACpF,CAAC;AAED;;;;;;GAMG;AACI,KAAK,kBAAkB,OAAqB,EAAE,EAAgB;IACnE,IAAA,8BAAiB,EAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IAChC,IAAA,wBAAW,EAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACpB,MAAM,EAAE,GAAG,IAAA,mBAAY,EAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IACtC,MAAM,EAAE,GAAG,IAAA,cAAO,EAAC,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,EAAE,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QACtB,MAAM,eAAe,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3C,OAAO;IACT,CAAC;IACD,MAAM,KAAK,GAAG,EAAE,CAAC,KAAkC,CAAC;IACpD,MAAM,SAAS,GAAG,IAAA,cAAM,GAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAA,2BAAqB,EAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAClF,MAAM,MAAM,GAAG,MAAM,IAAA,4BAAc,EAAC,OAAO,EAAE,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE;QACxE,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,SAAS;QAC1C,SAAS,EAAE,SAAS;QACpB,SAAS,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QACxD,YAAY;QACZ,KAAK,EAAE,IAAA,wBAAU,GAAE;KACpB,CAAC,CAAC;IACH,MAAM,IAAA,uBAAa,EAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrD,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,IAAA,4BAAe,EAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAChG,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/store/actions/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/store/actions/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAUnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAiCtD;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,YAAY,EACrB,EAAE,EAAE,eAAe,GAClB,OAAO,CAAC,UAAU,EAAE,CAAC,CAwBvB"}
|
|
@@ -3,20 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.searchItems = searchItems;
|
|
4
4
|
const paginate_1 = require("../../shared/dynamodb/paginate");
|
|
5
5
|
const scan_1 = require("../../shared/dynamodb/scan");
|
|
6
|
-
const
|
|
7
|
-
const filter_1 = require("../internal/filter");
|
|
6
|
+
const backend_search_1 = require("../internal/backend-search");
|
|
8
7
|
const item_mapper_1 = require("../internal/item-mapper");
|
|
9
8
|
const keys_1 = require("../internal/keys");
|
|
10
9
|
const query_1 = require("../internal/query");
|
|
11
10
|
const ranker_1 = require("../internal/ranker");
|
|
11
|
+
const search_filter_1 = require("../internal/search-filter");
|
|
12
12
|
const validation_1 = require("../internal/validation");
|
|
13
|
-
const get_1 = require("./get");
|
|
14
13
|
const DEFAULT_LIMIT = 10;
|
|
15
|
-
function passesFilter(item, op) {
|
|
16
|
-
if (!op.filter)
|
|
17
|
-
return true;
|
|
18
|
-
return (0, filter_1.matchesStoreFilter)(item.value, op.filter);
|
|
19
|
-
}
|
|
20
14
|
async function collectCandidates(context, op) {
|
|
21
15
|
const source = op.namespacePrefix.length > 0
|
|
22
16
|
? (0, paginate_1.paginateQuery)({
|
|
@@ -37,37 +31,12 @@ async function collectCandidates(context, op) {
|
|
|
37
31
|
if (!(0, keys_1.namespaceMatchesPrefix)(record.namespace, op.namespacePrefix))
|
|
38
32
|
continue;
|
|
39
33
|
const item = await (0, item_mapper_1.readStoreItem)(context, record);
|
|
40
|
-
if (!passesFilter(item, op))
|
|
34
|
+
if (!(0, search_filter_1.passesFilter)(item, op))
|
|
41
35
|
continue;
|
|
42
36
|
candidates.push({ item, embedding: record.embedding });
|
|
43
37
|
}
|
|
44
38
|
return candidates;
|
|
45
39
|
}
|
|
46
|
-
async function searchViaBackend(context, backend, index, op, offset, limit) {
|
|
47
|
-
const queryVector = await index.embeddings.embedQuery(op.query);
|
|
48
|
-
const need = offset + limit;
|
|
49
|
-
if (need > context.maxSearchCandidates) {
|
|
50
|
-
throw new errors_1.ValidationError(`Requested page (offset ${offset} + limit ${limit} = ${need}) exceeds maxSearchCandidates ` +
|
|
51
|
-
`(${context.maxSearchCandidates}); narrow the page or raise maxSearchCandidates`, 'maxSearchCandidates');
|
|
52
|
-
}
|
|
53
|
-
let topK = Math.min(need, context.maxSearchCandidates);
|
|
54
|
-
let results;
|
|
55
|
-
for (;;) {
|
|
56
|
-
const matches = await backend.query(op.namespacePrefix, queryVector, topK);
|
|
57
|
-
results = [];
|
|
58
|
-
for (const match of matches) {
|
|
59
|
-
if (!(0, keys_1.namespaceMatchesPrefix)(match.namespace, op.namespacePrefix))
|
|
60
|
-
continue;
|
|
61
|
-
const item = await (0, get_1.getItem)(context, match.namespace, match.key);
|
|
62
|
-
if (item && passesFilter(item, op))
|
|
63
|
-
results.push({ ...item, score: match.score });
|
|
64
|
-
}
|
|
65
|
-
if (results.length >= need || matches.length < topK || topK >= context.maxSearchCandidates)
|
|
66
|
-
break;
|
|
67
|
-
topK = Math.min(topK * 2, context.maxSearchCandidates);
|
|
68
|
-
}
|
|
69
|
-
return results;
|
|
70
|
-
}
|
|
71
40
|
/**
|
|
72
41
|
* Search items under a namespace prefix: metadata filtering plus optional
|
|
73
42
|
* semantic ranking. A non-empty prefix uses a native Query; an empty prefix
|
|
@@ -79,7 +48,7 @@ async function searchItems(context, op) {
|
|
|
79
48
|
const limit = op.limit ?? DEFAULT_LIMIT;
|
|
80
49
|
(0, validation_1.validatePaging)(offset, limit);
|
|
81
50
|
if (op.query && context.index && context.vectorBackend) {
|
|
82
|
-
const ranked = await searchViaBackend(context, context.vectorBackend, context.index, op, offset, limit);
|
|
51
|
+
const ranked = await (0, backend_search_1.searchViaBackend)(context, context.vectorBackend, context.index, op, offset, limit);
|
|
83
52
|
return ranked.slice(offset, offset + limit);
|
|
84
53
|
}
|
|
85
54
|
const candidates = await collectCandidates(context, op);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/store/actions/search.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/store/actions/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { IndexConfig, SearchItem, SearchOperation } from '@langchain/langgraph-checkpoint';
|
|
2
|
+
import type { VectorBackend } from '../vector-backend';
|
|
3
|
+
import type { StoreContext } from './setup';
|
|
4
|
+
export declare function searchViaBackend(context: StoreContext, backend: VectorBackend, index: IndexConfig, op: SearchOperation, offset: number, limit: number): Promise<SearchItem[]>;
|
|
5
|
+
//# sourceMappingURL=backend-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-search.d.ts","sourceRoot":"","sources":["../../../src/store/internal/backend-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,UAAU,EACV,eAAe,EAChB,MAAM,iCAAiC,CAAC;AAIzC,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,mBAAmB,CAAC;AAGpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA4C5C,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,WAAW,EAClB,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,UAAU,EAAE,CAAC,CA0BvB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.searchViaBackend = searchViaBackend;
|
|
4
|
+
const errors_1 = require("../../shared/errors/errors");
|
|
5
|
+
const get_1 = require("../actions/get");
|
|
6
|
+
const keys_1 = require("./keys");
|
|
7
|
+
const search_filter_1 = require("./search-filter");
|
|
8
|
+
/**
|
|
9
|
+
* Warn when a backend's own ordering disagrees with its scores. A backend
|
|
10
|
+
* returning a raw distance still hands back nearest-first, so the order looks
|
|
11
|
+
* right while every score means the opposite of what {@link VectorMatch.score}
|
|
12
|
+
* promises — ascending scores are that exact signature. Results are never
|
|
13
|
+
* reordered on this basis: a correctly-scored backend's order is authoritative.
|
|
14
|
+
*/
|
|
15
|
+
function warnOnNonDescendingScores(context, matches, namespacePrefix) {
|
|
16
|
+
const descending = matches.every((match, position) => position === 0 || matches[position - 1].score >= match.score);
|
|
17
|
+
if (descending)
|
|
18
|
+
return;
|
|
19
|
+
context.logger.warn('search: vectorBackend returned ascending scores; VectorMatch.score must be a relevance ' +
|
|
20
|
+
'(higher is better), not a distance — results are forwarded in the order the backend gave', { namespacePrefix });
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Read the canonical item a backend match points at, or `undefined` when the
|
|
24
|
+
* match is unusable. `getItem` validates, so a backend returning a namespace
|
|
25
|
+
* element containing the reserved separator would otherwise turn the whole
|
|
26
|
+
* search into a ValidationError instead of dropping the one bad match.
|
|
27
|
+
*/
|
|
28
|
+
async function fetchMatch(context, match) {
|
|
29
|
+
try {
|
|
30
|
+
return await (0, get_1.getItem)(context, match.namespace, match.key);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
context.logger.warn('search: skipped an unusable vectorBackend match', {
|
|
34
|
+
namespace: match.namespace,
|
|
35
|
+
key: match.key,
|
|
36
|
+
reason: error.name,
|
|
37
|
+
});
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function searchViaBackend(context, backend, index, op, offset, limit) {
|
|
42
|
+
const queryVector = await index.embeddings.embedQuery(op.query);
|
|
43
|
+
const need = offset + limit;
|
|
44
|
+
if (need > context.maxSearchCandidates) {
|
|
45
|
+
throw new errors_1.ValidationError(`Requested page (offset ${offset} + limit ${limit} = ${need}) exceeds maxSearchCandidates ` +
|
|
46
|
+
`(${context.maxSearchCandidates}); narrow the page or raise maxSearchCandidates`, 'maxSearchCandidates');
|
|
47
|
+
}
|
|
48
|
+
let topK = Math.min(need, context.maxSearchCandidates);
|
|
49
|
+
let results;
|
|
50
|
+
for (;;) {
|
|
51
|
+
const matches = await backend.query(op.namespacePrefix, queryVector, topK);
|
|
52
|
+
warnOnNonDescendingScores(context, matches, op.namespacePrefix);
|
|
53
|
+
results = [];
|
|
54
|
+
for (const match of matches) {
|
|
55
|
+
if (!(0, keys_1.namespaceMatchesPrefix)(match.namespace, op.namespacePrefix))
|
|
56
|
+
continue;
|
|
57
|
+
const item = await fetchMatch(context, match);
|
|
58
|
+
if (item && (0, search_filter_1.passesFilter)(item, op))
|
|
59
|
+
results.push({ ...item, score: match.score });
|
|
60
|
+
}
|
|
61
|
+
if (results.length >= need || matches.length < topK || topK >= context.maxSearchCandidates)
|
|
62
|
+
break;
|
|
63
|
+
topK = Math.min(topK * 2, context.maxSearchCandidates);
|
|
64
|
+
}
|
|
65
|
+
return results;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=backend-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-search.js","sourceRoot":"","sources":["../../../src/store/internal/backend-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../src/store/internal/filter.ts"],"names":[],"mappings":"AAEA,8DAA8D;AAC9D,MAAM,MAAM,SAAS,GACnB,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../src/store/internal/filter.ts"],"names":[],"mappings":"AAEA,8DAA8D;AAC9D,MAAM,MAAM,SAAS,GACnB,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAqEhF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAChC,OAAO,CAMT"}
|
|
@@ -2,13 +2,31 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.matchesStoreFilter = matchesStoreFilter;
|
|
4
4
|
const node_util_1 = require("node:util");
|
|
5
|
+
/**
|
|
6
|
+
* Ordered comparison over like-typed values only: numbers compare numerically,
|
|
7
|
+
* strings lexicographically, and a mismatched or unordered pair never matches.
|
|
8
|
+
*
|
|
9
|
+
* Deliberately stricter than both what this used to do and what upstream does.
|
|
10
|
+
* Native `>` coerces, so a stored `'10'` satisfied `{ $gt: 5 }` — inclusion
|
|
11
|
+
* decided by JS coercion rather than by the stored type. Upstream instead
|
|
12
|
+
* reduces both sides with `Number()`, which makes two ISO-8601 date strings
|
|
13
|
+
* `NaN` and every comparison between them false. Comparing like types
|
|
14
|
+
* directly is well-defined in both cases.
|
|
15
|
+
*/
|
|
16
|
+
function compareOrdered(actual, expected, test) {
|
|
17
|
+
const comparable = (typeof actual === 'number' && typeof expected === 'number') ||
|
|
18
|
+
(typeof actual === 'string' && typeof expected === 'string');
|
|
19
|
+
if (!comparable)
|
|
20
|
+
return false;
|
|
21
|
+
return test(actual === expected ? 0 : actual > expected ? 1 : -1);
|
|
22
|
+
}
|
|
5
23
|
const COMPARATORS = {
|
|
6
24
|
$eq: (actual, expected) => (0, node_util_1.isDeepStrictEqual)(actual, expected),
|
|
7
25
|
$ne: (actual, expected) => !(0, node_util_1.isDeepStrictEqual)(actual, expected),
|
|
8
|
-
$gt: (actual, expected) => actual >
|
|
9
|
-
$gte: (actual, expected) => actual >=
|
|
10
|
-
$lt: (actual, expected) => actual <
|
|
11
|
-
$lte: (actual, expected) => actual <=
|
|
26
|
+
$gt: (actual, expected) => compareOrdered(actual, expected, (order) => order > 0),
|
|
27
|
+
$gte: (actual, expected) => compareOrdered(actual, expected, (order) => order >= 0),
|
|
28
|
+
$lt: (actual, expected) => compareOrdered(actual, expected, (order) => order < 0),
|
|
29
|
+
$lte: (actual, expected) => compareOrdered(actual, expected, (order) => order <= 0),
|
|
12
30
|
$in: (actual, expected) => Array.isArray(expected)
|
|
13
31
|
? expected.some((candidate) => (0, node_util_1.isDeepStrictEqual)(actual, candidate))
|
|
14
32
|
: false,
|
|
@@ -40,6 +58,9 @@ function matchesCondition(actual, condition) {
|
|
|
40
58
|
* is exact-match ($eq); an operator object ({ $gt: 4 }) applies comparisons.
|
|
41
59
|
*/
|
|
42
60
|
function matchesStoreFilter(value, filter) {
|
|
43
|
-
return Object.entries(filter).every(([field, condition]) =>
|
|
61
|
+
return Object.entries(filter).every(([field, condition]) =>
|
|
62
|
+
/** Own properties only: `value['toString']` would otherwise resolve up the
|
|
63
|
+
* prototype chain and be compared as if it were stored data. */
|
|
64
|
+
matchesCondition(Object.hasOwn(value, field) ? value[field] : undefined, condition));
|
|
44
65
|
}
|
|
45
66
|
//# sourceMappingURL=filter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../src/store/internal/filter.ts"],"names":[],"mappings":";;;AAAA,yCAA8C;AAM9C,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../src/store/internal/filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-reconcile.d.ts","sourceRoot":"","sources":["../../../src/store/internal/index-reconcile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAMlE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index-reconcile.d.ts","sourceRoot":"","sources":["../../../src/store/internal/index-reconcile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAMlE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG5C,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CACjC;AAOD;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,eAAe,EAAE,CAAC,CAe5B;AAED,6EAA6E;AAC7E,wBAAsB,cAAc,CAClC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,eAAe,EAAE,GACzB,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,WAAW,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,SAAS,EAAE,CAO5F;AAeD,8EAA8E;AAC9E,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,eAAe,EAAE,GACtB,OAAO,CAAC,MAAM,CAAC,CA6BjB"}
|
|
@@ -9,6 +9,7 @@ const item_mapper_1 = require("./item-mapper");
|
|
|
9
9
|
const keys_1 = require("./keys");
|
|
10
10
|
const query_1 = require("./query");
|
|
11
11
|
const semantic_search_1 = require("./semantic-search");
|
|
12
|
+
const write_verify_1 = require("./write-verify");
|
|
12
13
|
/** Stable, collision-free identity for a (namespace, key) pair. */
|
|
13
14
|
function refIdentity(namespace, key) {
|
|
14
15
|
return JSON.stringify([...namespace, key]);
|
|
@@ -54,16 +55,45 @@ function selectOrphans(backendRefs, live) {
|
|
|
54
55
|
.map((target) => refIdentity(target.namespace, target.key)));
|
|
55
56
|
return backendRefs.filter((ref) => !liveKeys.has(refIdentity(ref.namespace, ref.key)));
|
|
56
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* True when a candidate's canonical item is confirmed absent right now. The
|
|
60
|
+
* live-set snapshot and this read are not one point in time, so an item
|
|
61
|
+
* written between them looks orphaned even though it is live — and deleting
|
|
62
|
+
* its vector would silently drop a just-written item out of semantic search.
|
|
63
|
+
*/
|
|
64
|
+
async function confirmedGone(context, ref) {
|
|
65
|
+
return (0, write_verify_1.rowIsAbsent)(context, {
|
|
66
|
+
PK: (0, keys_1.partitionKey)(ref.namespace),
|
|
67
|
+
SK: (0, keys_1.sortKey)(ref.namespace, ref.key),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
57
70
|
/** Delete backend vectors with no canonical item; returns the prune count. */
|
|
58
71
|
async function pruneOrphans(context, backend, prefix, live) {
|
|
59
72
|
if (!backend.listKeys) {
|
|
60
73
|
context.logger.info('reconcileVectorIndex prune skipped: backend has no listKeys', { prefix });
|
|
61
74
|
return 0;
|
|
62
75
|
}
|
|
63
|
-
const
|
|
64
|
-
|
|
76
|
+
const candidates = selectOrphans(await backend.listKeys(prefix), live);
|
|
77
|
+
/**
|
|
78
|
+
* Every item the snapshot actually saw, embedded or not. A candidate in here
|
|
79
|
+
* is prunable on the evidence already gathered — its item exists but yields
|
|
80
|
+
* no embedding (its indexable text became empty), so its vector really is
|
|
81
|
+
* stale. Only a candidate the snapshot never saw at all is ambiguous.
|
|
82
|
+
*/
|
|
83
|
+
const observed = new Set(live.map((target) => refIdentity(target.namespace, target.key)));
|
|
84
|
+
let pruned = 0;
|
|
85
|
+
for (const ref of candidates) {
|
|
86
|
+
if (!observed.has(refIdentity(ref.namespace, ref.key)) &&
|
|
87
|
+
!(await confirmedGone(context, ref))) {
|
|
88
|
+
context.logger.info('reconcileVectorIndex: kept a vector whose item reappeared', {
|
|
89
|
+
namespace: ref.namespace,
|
|
90
|
+
key: ref.key,
|
|
91
|
+
});
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
65
94
|
await backend.delete(ref.namespace, ref.key);
|
|
95
|
+
pruned += 1;
|
|
66
96
|
}
|
|
67
|
-
return
|
|
97
|
+
return pruned;
|
|
68
98
|
}
|
|
69
99
|
//# sourceMappingURL=index-reconcile.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-reconcile.js","sourceRoot":"","sources":["../../../src/store/internal/index-reconcile.ts"],"names":[],"mappings":";;;;;;AAAA,6DAA+D;AAI/D,+CAA8C;AAC9C,
|
|
1
|
+
{"version":3,"file":"index-reconcile.js","sourceRoot":"","sources":["../../../src/store/internal/index-reconcile.ts"],"names":[],"mappings":";;;;;;AAAA,6DAA+D;AAI/D,+CAA8C;AAC9C,iCAAuE;AACvE,mCAAsC;AACtC,uDAA+C;AAE/C,iDAA6C;AAS7C,mEAAmE;AACnE,SAAS,WAAW,CAAC,SAAmB,EAAE,GAAW;IACnD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACI,KAAK,kCACV,OAAqB,EACrB,MAAgB;IAEhB,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,IAAA,wBAAa,EAAC;QAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,IAAA,mBAAW,EAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;QAC9C,QAAQ,EAAE,OAAO,CAAC,YAAY;KAC/B,CAAC,CAAC;IACH,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,GAAsB,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,IAAA,6BAAsB,EAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC;YAAE,SAAS;QACrF,MAAM,IAAI,GAAG,MAAM,IAAA,2BAAa,EAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,MAAM,IAAA,4BAAU,EAAC,OAAO,EAAE,IAAI,CAAC,KAAkC,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,6EAA6E;AACtE,KAAK,yBACV,OAAsB,EACtB,OAA0B;IAE1B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,SAAS;QAChC,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACrE,QAAQ,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,6EAA6E;AAC7E,uBAA8B,WAAwB,EAAE,IAAuB;IAC7E,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB,IAAI;SACD,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC;SAClD,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAC9D,CAAC;IACF,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACzF,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,aAAa,CAAC,OAAqB,EAAE,GAAc;IAChE,OAAO,IAAA,0BAAW,EAAC,OAAO,EAAE;QAC1B,EAAE,EAAE,IAAA,mBAAY,EAAC,GAAG,CAAC,SAAS,CAAC;QAC/B,EAAE,EAAE,IAAA,cAAO,EAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC;KACpC,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AACvE,KAAK,uBACV,OAAqB,EACrB,OAAsB,EACtB,MAAgB,EAChB,IAAuB;IAEvB,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,6DAA6D,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/F,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;IACvE;;;;;OAKG;IACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1F,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,IACE,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;YAClD,CAAC,CAAC,MAAM,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,EACpC,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,2DAA2D,EAAE;gBAC/E,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,GAAG,EAAE,GAAG,CAAC,GAAG;aACb,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7C,MAAM,IAAI,CAAC,CAAC;IACd,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Separator joining namespace elements (and the trailing key) in the sort key. */
|
|
2
2
|
export declare const NAMESPACE_SEPARATOR = "#";
|
|
3
|
-
/** Partition key for an item: the scope-root
|
|
3
|
+
/** Partition key for an item: the adapter tag plus the scope-root element. */
|
|
4
4
|
export declare function partitionKey(namespace: string[]): string;
|
|
5
5
|
/** Sort key: the rest of the namespace plus the key, separator-joined. */
|
|
6
6
|
export declare function sortKey(namespace: string[], key: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/store/internal/keys.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/store/internal/keys.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,MAAM,CAAC;AASvC,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAExD;AAED,0EAA0E;AAC1E,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAGtD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAGrF"}
|
|
@@ -7,9 +7,15 @@ exports.sortKeyPrefix = sortKeyPrefix;
|
|
|
7
7
|
exports.namespaceMatchesPrefix = namespaceMatchesPrefix;
|
|
8
8
|
/** Separator joining namespace elements (and the trailing key) in the sort key. */
|
|
9
9
|
exports.NAMESPACE_SEPARATOR = '#';
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Adapter tag prefixed to every store partition key — see the equivalent in
|
|
12
|
+
* checkpointer/internal/keys.ts for why the three adapters' partitions must
|
|
13
|
+
* not overlap on a shared table.
|
|
14
|
+
*/
|
|
15
|
+
const ADAPTER_PARTITION_PREFIX = `STORE${exports.NAMESPACE_SEPARATOR}`;
|
|
16
|
+
/** Partition key for an item: the adapter tag plus the scope-root element. */
|
|
11
17
|
function partitionKey(namespace) {
|
|
12
|
-
return namespace[0]
|
|
18
|
+
return `${ADAPTER_PARTITION_PREFIX}${namespace[0]}`;
|
|
13
19
|
}
|
|
14
20
|
/** Sort key: the rest of the namespace plus the key, separator-joined. */
|
|
15
21
|
function sortKey(namespace, key) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../../src/store/internal/keys.ts"],"names":[],"mappings":";;;;;;;AAAA,mFAAmF;AACtE,QAAA,mBAAmB,GAAG,GAAG,CAAC;AAEvC,
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../../src/store/internal/keys.ts"],"names":[],"mappings":";;;;;;;AAAA,mFAAmF;AACtE,QAAA,mBAAmB,GAAG,GAAG,CAAC;AAEvC;;;;GAIG;AACH,MAAM,wBAAwB,GAAG,QAAQ,QAAA,mBAAmB,EAAE,CAAC;AAE/D,8EAA8E;AAC9E,sBAA6B,SAAmB;IAC9C,OAAO,GAAG,wBAAwB,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;AACtD,CAAC;AAED,0EAA0E;AAC1E,iBAAwB,SAAmB,EAAE,GAAW;IACtD,OAAO,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,QAAA,mBAAmB,CAAC,CAAC;AAChE,CAAC;AAED;;;;GAIG;AACH,uBAA8B,MAAgB;IAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,QAAA,mBAAmB,CAAC,GAAG,QAAA,mBAAmB,EAAE,CAAC;AAC5F,CAAC;AAED;;;GAGG;AACH,gCAAuC,SAAmB,EAAE,MAAgB;IAC1E,IAAI,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../../src/store/internal/persist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAmB,MAAM,0BAA0B,CAAC;AAInF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../../src/store/internal/persist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAmB,MAAM,0BAA0B,CAAC;AAInF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG5C;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,aAAa,EAAE,iBAAiB,GAAG,SAAS,GAC3C,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
|
|
@@ -6,10 +6,6 @@ const descriptor_keys_1 = require("../../shared/codec/descriptor-keys");
|
|
|
6
6
|
const orphans_1 = require("../../shared/codec/s3/orphans");
|
|
7
7
|
const retry_1 = require("../../shared/dynamodb/retry");
|
|
8
8
|
const write_verify_1 = require("./write-verify");
|
|
9
|
-
/** True when `error` is a {@link RetryExhaustedError} — checked by name, not `instanceof` (banned repo-wide). */
|
|
10
|
-
function isRetryExhausted(error) {
|
|
11
|
-
return error.name === 'RetryExhaustedError';
|
|
12
|
-
}
|
|
13
9
|
/**
|
|
14
10
|
* Put the record: on a definite failure, clean up *this* record's nonced S3
|
|
15
11
|
* object; on an ambiguous retry-exhaustion failure, verify via
|
|
@@ -21,7 +17,7 @@ async function persistRecord(context, record, previousValue) {
|
|
|
21
17
|
await (0, retry_1.withDynamoDBRetry)(() => context.client.put({ TableName: context.tableName, Item: record }));
|
|
22
18
|
}
|
|
23
19
|
catch (error) {
|
|
24
|
-
const landed = isRetryExhausted(error) &&
|
|
20
|
+
const landed = (0, write_verify_1.isRetryExhausted)(error) &&
|
|
25
21
|
record.value.location === codec_1.PayloadLocation.S3 &&
|
|
26
22
|
(await (0, write_verify_1.writeLandedAt)(context, record, record.value.s3Key));
|
|
27
23
|
if (!landed) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persist.js","sourceRoot":"","sources":["../../../src/store/internal/persist.ts"],"names":[],"mappings":";;;AAAA,oDAAmF;AACnF,wEAAmE;AACnE,2DAAiE;AACjE,uDAAgE;AAGhE,
|
|
1
|
+
{"version":3,"file":"persist.js","sourceRoot":"","sources":["../../../src/store/internal/persist.ts"],"names":[],"mappings":";;;AAAA,oDAAmF;AACnF,wEAAmE;AACnE,2DAAiE;AACjE,uDAAgE;AAGhE,iDAAiE;AAEjE;;;;;GAKG;AACI,KAAK,wBACV,OAAqB,EACrB,MAAuB,EACvB,aAA4C;IAE5C,IAAI,CAAC;QACH,MAAM,IAAA,yBAAiB,EAAC,GAAG,EAAE,CAC3B,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CACnE,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GACV,IAAA,+BAAgB,EAAC,KAAc,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,uBAAe,CAAC,EAAE;YAC5C,CAAC,MAAM,IAAA,4BAAa,EAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACtB,MAAM,IAAA,0BAAgB,EACpB,OAAO,CAAC,SAAS,EACjB,IAAA,+BAAa,EAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAC7B,WAAW,EACX,OAAO,CAAC,MAAM,CACf,CAAC;YACJ,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,SAAS,IAAI,aAAa,EAAE,CAAC;QACvC,MAAM,IAAA,0BAAgB,EACpB,OAAO,CAAC,SAAS,EACjB,IAAA,+BAAa,EAAC,CAAC,aAAa,CAAC,CAAC,EAC9B,qBAAqB,EACrB,OAAO,CAAC,MAAM,CACf,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Item, SearchOperation } from '@langchain/langgraph-checkpoint';
|
|
2
|
+
/** True when `item` satisfies the search operation's optional metadata filter. */
|
|
3
|
+
export declare function passesFilter(item: Item, op: SearchOperation): boolean;
|
|
4
|
+
//# sourceMappingURL=search-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-filter.d.ts","sourceRoot":"","sources":["../../../src/store/internal/search-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAI7E,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,eAAe,GAAG,OAAO,CAMrE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.passesFilter = passesFilter;
|
|
4
|
+
const filter_1 = require("./filter");
|
|
5
|
+
/** True when `item` satisfies the search operation's optional metadata filter. */
|
|
6
|
+
function passesFilter(item, op) {
|
|
7
|
+
if (!op.filter)
|
|
8
|
+
return true;
|
|
9
|
+
return (0, filter_1.matchesStoreFilter)(item.value, op.filter);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=search-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-filter.js","sourceRoot":"","sources":["../../../src/store/internal/search-filter.ts"],"names":[],"mappings":";;;AAEA,qCAA8D;AAE9D,kFAAkF;AAClF,sBAA6B,IAAU,EAAE,EAAmB;IAC1D,IAAI,CAAC,EAAE,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO,IAAA,2BAAkB,EACvB,IAAI,CAAC,KAAkC,EACvC,EAAE,CAAC,MAAmC,CACvC,CAAC;AACJ,CAAC"}
|
|
@@ -27,6 +27,16 @@ export interface StoreSetup {
|
|
|
27
27
|
ddbClient: DynamoDBClient | undefined;
|
|
28
28
|
ownsClient: boolean;
|
|
29
29
|
}
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the client, optional S3 offloader, serializer, and index config.
|
|
32
|
+
*
|
|
33
|
+
* A `vectorBackend` without an `index` is rejected outright rather than
|
|
34
|
+
* silently degrading: with no embeddings configured, every `put` would compute
|
|
35
|
+
* no vector and instruct the backend to *delete* the item's entry instead of
|
|
36
|
+
* indexing it, and `search()` would fall through to an unranked scan-order
|
|
37
|
+
* listing with no `.score` field and no error — a semantic query returning a
|
|
38
|
+
* normal-looking but meaningless response. `reconcileVectorIndex` already
|
|
39
|
+
* refused this exact misconfiguration.
|
|
40
|
+
*/
|
|
31
41
|
export declare function setUpStore(options: DynamoDBStoreOptions): StoreSetup;
|
|
32
42
|
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/store/internal/setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAEvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGxE,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/store/internal/setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAEvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGxE,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAQ9D,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,2DAA2D;AAC3D,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,oDAAoD;AACpD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,YAAY,CAAC;IACtB,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,oBAAoB,GAAG,UAAU,CAiCpE"}
|
|
@@ -6,9 +6,25 @@ const config_1 = require("../../shared/codec/s3/config");
|
|
|
6
6
|
const offloader_1 = require("../../shared/codec/s3/offloader");
|
|
7
7
|
const constants_1 = require("../../shared/constants");
|
|
8
8
|
const client_1 = require("../../shared/dynamodb/client");
|
|
9
|
+
const errors_1 = require("../../shared/errors/errors");
|
|
9
10
|
const logger_1 = require("../../shared/logging/logger");
|
|
10
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the client, optional S3 offloader, serializer, and index config.
|
|
13
|
+
*
|
|
14
|
+
* A `vectorBackend` without an `index` is rejected outright rather than
|
|
15
|
+
* silently degrading: with no embeddings configured, every `put` would compute
|
|
16
|
+
* no vector and instruct the backend to *delete* the item's entry instead of
|
|
17
|
+
* indexing it, and `search()` would fall through to an unranked scan-order
|
|
18
|
+
* listing with no `.score` field and no error — a semantic query returning a
|
|
19
|
+
* normal-looking but meaningless response. `reconcileVectorIndex` already
|
|
20
|
+
* refused this exact misconfiguration.
|
|
21
|
+
*/
|
|
11
22
|
function setUpStore(options) {
|
|
23
|
+
if (options.vectorBackend && !options.index) {
|
|
24
|
+
throw new errors_1.ValidationError('vectorBackend requires a configured `index` (dims + embeddings); without one no embedding ' +
|
|
25
|
+
'is computed, every put would clear the item vector, and search would silently return ' +
|
|
26
|
+
'unranked, score-less results', 'vectorBackend');
|
|
27
|
+
}
|
|
12
28
|
const resolved = (0, client_1.resolveDynamoDBClient)(options);
|
|
13
29
|
return {
|
|
14
30
|
context: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/store/internal/setup.ts"],"names":[],"mappings":";;;AAKA,8DAA2D;AAC3D,yDAAuE;AACvE,+DAA8D;AAC9D,sDAIgC;AAChC,yDAAqE;AACrE,wDAAyE;AA2BzE
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/store/internal/setup.ts"],"names":[],"mappings":";;;AAKA,8DAA2D;AAC3D,yDAAuE;AACvE,+DAA8D;AAC9D,sDAIgC;AAChC,yDAAqE;AACrE,uDAA6D;AAC7D,wDAAyE;AA2BzE;;;;;;;;;;GAUG;AACH,oBAA2B,OAA6B;IACtD,IAAI,OAAO,CAAC,aAAa,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC5C,MAAM,IAAI,wBAAe,CACvB,4FAA4F;YAC1F,uFAAuF;YACvF,8BAA8B,EAChC,eAAe,CAChB,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAChD,OAAO;QACL,OAAO,EAAE;YACP,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,uBAAU;YAClC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,SAAS,EAAE,OAAO,CAAC,EAAE;gBACnB,CAAC,CAAC,IAAI,uBAAW,CAAC;oBACd,GAAG,OAAO,CAAC,EAAE;oBACb,SAAS,EACP,OAAO,CAAC,EAAE,CAAC,SAAS,IAAI,IAAA,gCAAuB,EAAC,iCAAqB,EAAE,OAAO,CAAC;iBAClF,CAAC;gBACJ,CAAC,CAAC,SAAS;YACb,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,MAAM,EAAE,IAAA,sBAAa,EAAC,OAAO,CAAC,MAAM,CAAC;YACrC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,IAAI,yCAA6B;YACjF,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,qCAAyB;SAChE;QACD,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,UAAU,EAAE,QAAQ,CAAC,UAAU;KAChC,CAAC;AACJ,CAAC"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
/** Validate search/listNamespaces paging is non-negative integers. */
|
|
2
2
|
export declare function validatePaging(offset: number, limit: number): void;
|
|
3
|
-
/** Validate the namespace is non-empty and each element is
|
|
3
|
+
/** Validate the namespace is non-empty and each element is a valid identifier. */
|
|
4
4
|
export declare function validateNamespace(namespace: string[]): void;
|
|
5
|
-
/** Validate an item key is a non-empty, separator-free string. */
|
|
5
|
+
/** Validate an item key is a non-empty, separator- and control-char-free string. */
|
|
6
6
|
export declare function validateKey(key: string): void;
|
|
7
|
+
/**
|
|
8
|
+
* Validate an optional namespace depth cap. Left unchecked, a negative value
|
|
9
|
+
* silently inverted truncation via `Array.prototype.slice(0, -n)`, which drops
|
|
10
|
+
* the *last* n elements rather than erroring.
|
|
11
|
+
*/
|
|
12
|
+
export declare function validateMaxDepth(maxDepth?: number): void;
|
|
7
13
|
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/store/internal/validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/store/internal/validation.ts"],"names":[],"mappings":"AAOA,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAGlE;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAK3D;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAGxD"}
|