@resistdesign/voltra 3.0.0-alpha.36 → 3.0.0-alpha.38

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.
@@ -74,6 +74,40 @@ export type GetItemOutput = {
74
74
  */
75
75
  Item?: AttributeMap;
76
76
  };
77
+ /**
78
+ * Input payload for DynamoDB put item operations.
79
+ */
80
+ export type PutItemInput = {
81
+ /**
82
+ * DynamoDB table name.
83
+ */
84
+ TableName: string;
85
+ /**
86
+ * Item attributes to store.
87
+ */
88
+ Item: AttributeMap;
89
+ /**
90
+ * Optional conditional expression.
91
+ */
92
+ ConditionExpression?: string;
93
+ /**
94
+ * Optional expression attribute names.
95
+ */
96
+ ExpressionAttributeNames?: Record<string, string>;
97
+ /**
98
+ * Optional expression attribute values.
99
+ */
100
+ ExpressionAttributeValues?: AttributeMap;
101
+ };
102
+ /**
103
+ * Output payload from DynamoDB put item operations.
104
+ */
105
+ export type PutItemOutput = {
106
+ /**
107
+ * True when conditional write failed.
108
+ */
109
+ conditionFailed?: boolean;
110
+ };
77
111
  /**
78
112
  * DynamoDB batch write request entry.
79
113
  */
@@ -113,6 +147,12 @@ export type DynamoBatchWriter = {
113
147
  * @returns Get item output payload.
114
148
  */
115
149
  getItem(input: GetItemInput): Promise<GetItemOutput>;
150
+ /**
151
+ * Execute a DynamoDB put item operation.
152
+ * @param input Put item input payload.
153
+ * @returns Put item output payload.
154
+ */
155
+ putItem(input: PutItemInput): Promise<PutItemOutput>;
116
156
  };
117
157
  /**
118
158
  * Input payload for DynamoDB query operations.
@@ -89,6 +89,23 @@ export type StructuredDocFieldsItem = StructuredDocFieldsKey & {
89
89
  * Structured fields stored for the document.
90
90
  */
91
91
  fields: StructuredDocFieldsRecord;
92
+ /**
93
+ * Monotonic version used for optimistic concurrency control.
94
+ */
95
+ version: number;
96
+ };
97
+ /**
98
+ * Loaded document fields state with version.
99
+ */
100
+ export type StructuredDocFieldsState = {
101
+ /**
102
+ * Structured fields persisted for the document.
103
+ */
104
+ fields: StructuredDocFieldsRecord;
105
+ /**
106
+ * Monotonic version for optimistic writes.
107
+ */
108
+ version: number;
92
109
  };
93
110
  /**
94
111
  * Schema metadata for the structured term index table.
@@ -115,6 +132,7 @@ export declare const structuredRangeIndexSchema: {
115
132
  export declare const structuredDocFieldsSchema: {
116
133
  readonly partitionKey: "docId";
117
134
  readonly fieldsAttribute: "fields";
135
+ readonly versionAttribute: "version";
118
136
  };
119
137
  /**
120
138
  * Serialize a structured value for DynamoDB key usage.
@@ -163,4 +181,4 @@ export declare function buildStructuredRangeItem(field: string, value: WhereValu
163
181
  * @param fields Structured fields to store.
164
182
  * @returns Structured doc fields item.
165
183
  */
166
- export declare function buildStructuredDocFieldsItem(docId: DocId, fields: StructuredDocFieldsRecord): StructuredDocFieldsItem;
184
+ export declare function buildStructuredDocFieldsItem(docId: DocId, fields: StructuredDocFieldsRecord, version: number): StructuredDocFieldsItem;
@@ -7,7 +7,8 @@ import type { DynamoQueryClient } from "../ddb/Types";
7
7
  import type { DocId } from "../Types";
8
8
  import type { StructuredSearchDependencies } from "./SearchStructured";
9
9
  import type { StructuredQueryOptions, WhereValue } from "./Types";
10
- import { StructuredDdbWriter } from "./StructuredWriter";
10
+ import type { StructuredStringTokenizerConfig } from "./StructuredStringLike";
11
+ import { StructuredDdbWriter, type StructuredWriterOptions } from "./StructuredWriter";
11
12
  /**
12
13
  * Deployment-specific DynamoDB table names required for structured indexing.
13
14
  */
@@ -24,6 +25,8 @@ export type StructuredTableNames = {
24
25
  type StructuredDdbConfig = {
25
26
  client: DynamoQueryClient;
26
27
  tables: StructuredTableNames;
28
+ writerOptions?: StructuredWriterOptions;
29
+ tokenizer?: Partial<StructuredStringTokenizerConfig>;
27
30
  };
28
31
  /**
29
32
  * Read-only structured queries against DynamoDB term/range indexes.
@@ -8,12 +8,18 @@ import type { DocId } from "../Types";
8
8
  import type { StructuredSearchDependencies } from "./SearchStructured";
9
9
  import type { StructuredWriter } from "./Handlers";
10
10
  import type { StructuredDocFieldsRecord } from "./StructuredDdb";
11
+ import type { StructuredStringTokenizerConfig } from "./StructuredStringLike";
11
12
  /**
12
13
  * In-memory structured backend for tests and local usage.
13
14
  */
14
15
  export declare class StructuredInMemoryBackend implements StructuredSearchDependencies, StructuredWriter {
16
+ private readonly tokenizer?;
15
17
  private docFields;
16
18
  private index;
19
+ /**
20
+ * @param tokenizer Optional tokenizer overrides for structured string contains behavior.
21
+ */
22
+ constructor(tokenizer?: Partial<StructuredStringTokenizerConfig> | undefined);
17
23
  private rebuildIndex;
18
24
  private buildPage;
19
25
  /**
@@ -1,9 +1,12 @@
1
1
  import type { DocId } from "../Types";
2
+ import { type StructuredStringTokenizerConfig } from "./StructuredStringLike";
2
3
  import type { CandidatePage, StructuredQueryOptions, WhereValue } from "./Types";
3
4
  /**
4
5
  * In-memory structured index that builds term/contains/range postings.
5
6
  */
6
7
  export declare class StructuredInMemoryIndex {
8
+ private readonly tokenizer?;
9
+ constructor(tokenizer?: Partial<StructuredStringTokenizerConfig> | undefined);
7
10
  private eqIndex;
8
11
  private containsIndex;
9
12
  private rangeIndex;
@@ -3,6 +3,35 @@ import type { WhereValue } from "./Types";
3
3
  * Prefix marker for structured string contains tokens.
4
4
  */
5
5
  export declare const STRUCTURED_STRING_CONTAINS_TOKEN_PREFIX = "__str__:";
6
+ /**
7
+ * Tokenizer settings for structured string contains/LIKE behavior.
8
+ */
9
+ export type StructuredStringTokenizerConfig = {
10
+ /**
11
+ * Minimum ngram size to generate.
12
+ */
13
+ minNgramSize: number;
14
+ /**
15
+ * Maximum ngram size to generate.
16
+ */
17
+ maxNgramSize: number;
18
+ /**
19
+ * Maximum source string length to tokenize.
20
+ */
21
+ maxIndexedStringLength: number;
22
+ /**
23
+ * Maximum number of tokens emitted per value.
24
+ */
25
+ maxTokensPerValue: number;
26
+ };
27
+ /**
28
+ * Safe defaults that preserve current behavior.
29
+ */
30
+ export declare const DEFAULT_STRUCTURED_STRING_TOKENIZER_CONFIG: StructuredStringTokenizerConfig;
31
+ /**
32
+ * Resolve tokenizer config with validation and sane defaults.
33
+ */
34
+ export declare const resolveStructuredStringTokenizerConfig: (config?: Partial<StructuredStringTokenizerConfig>) => StructuredStringTokenizerConfig;
6
35
  /**
7
36
  * Normalize a string for structured LIKE matching.
8
37
  * - lowercase
@@ -13,12 +42,12 @@ export declare const normalizeStructuredLikeString: (value: string) => string;
13
42
  /**
14
43
  * Build contains tokens for an indexed structured string field value.
15
44
  */
16
- export declare const buildStructuredStringContainsTokens: (value: string) => string[];
45
+ export declare const buildStructuredStringContainsTokens: (value: string, tokenizerConfig?: Partial<StructuredStringTokenizerConfig>) => string[];
17
46
  /**
18
47
  * Build contains tokens for a SQL-like pattern. `%` and `_` are wildcard
19
48
  * markers; when no wildcard exists, value behaves as `%value%`.
20
49
  */
21
- export declare const buildStructuredLikePatternTokens: (value: string) => string[];
50
+ export declare const buildStructuredLikePatternTokens: (value: string, tokenizerConfig?: Partial<StructuredStringTokenizerConfig>) => string[];
22
51
  /**
23
52
  * True when this contains query value is a generated string token.
24
53
  */
@@ -1,5 +1,6 @@
1
1
  import type { DocId } from "../Types";
2
- import type { StructuredDocFieldsRecord, StructuredRangeIndexItem, StructuredRangeIndexKey, StructuredTermIndexItem, StructuredTermIndexKey } from "./StructuredDdb";
2
+ import type { StructuredDocFieldsState, StructuredDocFieldsRecord, StructuredRangeIndexItem, StructuredRangeIndexKey, StructuredTermIndexItem, StructuredTermIndexKey } from "./StructuredDdb";
3
+ import { type StructuredStringTokenizerConfig } from "./StructuredStringLike";
3
4
  /**
4
5
  * Dependencies required to persist structured index entries.
5
6
  */
@@ -9,14 +10,15 @@ export type StructuredWriterDependencies = {
9
10
  * @param docId Document id to load.
10
11
  * @returns Stored fields or undefined when missing.
11
12
  */
12
- loadDocFields(docId: DocId): Promise<StructuredDocFieldsRecord | undefined>;
13
+ loadDocFieldsState(docId: DocId): Promise<StructuredDocFieldsState | undefined>;
13
14
  /**
14
- * Store the latest fields for a document.
15
+ * Compare-and-swap the latest fields for a document.
15
16
  * @param docId Document id to store.
17
+ * @param expectedVersion Version expected by the caller.
16
18
  * @param fields Structured fields to persist.
17
- * @returns Promise resolved once stored.
19
+ * @returns True when swap succeeds, false on version mismatch.
18
20
  */
19
- putDocFields(docId: DocId, fields: StructuredDocFieldsRecord): Promise<void>;
21
+ putDocFieldsIfVersion(docId: DocId, expectedVersion: number | undefined, fields: StructuredDocFieldsRecord): Promise<boolean>;
20
22
  /**
21
23
  * Store term index entries.
22
24
  * @param entries Term entries to store.
@@ -42,15 +44,26 @@ export type StructuredWriterDependencies = {
42
44
  */
43
45
  deleteRangeEntries(entries: StructuredRangeIndexKey[]): Promise<void>;
44
46
  };
47
+ export type StructuredWriterOptions = {
48
+ /**
49
+ * Optional tokenizer settings for string contains indexing.
50
+ */
51
+ tokenizer?: Partial<StructuredStringTokenizerConfig>;
52
+ /**
53
+ * Maximum compare-and-swap retries for concurrent writes.
54
+ */
55
+ maxConcurrentWriteRetries?: number;
56
+ };
45
57
  /**
46
58
  * Writer that diffs structured fields and persists term/range entries.
47
59
  */
48
60
  export declare class StructuredDdbWriter {
49
61
  private readonly dependencies;
62
+ private readonly options;
50
63
  /**
51
64
  * @param dependencies Writer dependencies for persistence.
52
65
  */
53
- constructor(dependencies: StructuredWriterDependencies);
66
+ constructor(dependencies: StructuredWriterDependencies, options?: StructuredWriterOptions);
54
67
  /**
55
68
  * Write structured fields for a document, diffing term/range entries.
56
69
  * @param docId Document id to write.
@@ -5,9 +5,9 @@
5
5
  * and optionally provide DAC and indexing integrations. The constructor validates
6
6
  * configuration once, and each call resolves drivers as needed.
7
7
  */
8
- import { LiteralValue, TypeInfo, TypeInfoDataItem, TypeInfoMap, TypeOperation } from "../../common/TypeParsing/TypeInfo";
8
+ import { LiteralValue, TypeInfo, TypeInfoDataItem, TypeInfoField, TypeInfoMap, TypeOperation } from "../../common/TypeParsing/TypeInfo";
9
9
  import { CustomTypeInfoFieldValidatorMap } from "../../common/TypeParsing/Validation";
10
- import { ListItemsConfig, ListItemsResults, ListRelationshipsConfig } from "../../common/SearchTypes";
10
+ import { ComparisonOperators, FieldCriterion, ListItemsConfig, ListItemsResults, ListRelationshipsConfig, SearchCriteria } from "../../common/SearchTypes";
11
11
  import { DeleteRelationshipResults, RelationshipOperation, TypeInfoORMAPI, TypeInfoORMContext } from "../../common/TypeInfoORM";
12
12
  import { DataItemDBDriver, IndexingRelationshipDriver, ItemRelationshipDBDriver } from "./drivers";
13
13
  import { BaseItemRelationshipInfo, ItemRelationshipInfo, ItemRelationshipInfoKeys, ItemRelationshipInfoType, ItemRelationshipOriginatingItemInfo } from "../../common/ItemRelationshipInfoTypes";
@@ -18,6 +18,7 @@ import type { StructuredWriter } from "../Indexing/structured/Handlers";
18
18
  import type { ResolvedSearchLimits } from "../Indexing/Handler/Config";
19
19
  import type { StructuredDocFieldsRecord } from "../Indexing/structured/StructuredDdb";
20
20
  import type { Where, WhereValue } from "../Indexing/structured/Types";
21
+ import type { StructuredStringTokenizerConfig } from "../Indexing/structured/StructuredStringLike";
21
22
  import type { RelationalBackend } from "./drivers/IndexingRelationshipDriver";
22
23
  /**
23
24
  * Strip a relationship item down to its identifying keys.
@@ -91,9 +92,9 @@ export type TypeInfoORMIndexingConfig = {
91
92
  */
92
93
  backend: IndexBackend;
93
94
  /**
94
- * Default index field names by type.
95
+ * Default index field name(s) by type.
95
96
  */
96
- defaultIndexFieldByType?: Record<string, string>;
97
+ defaultIndexFieldByType?: Record<string, string | string[]>;
97
98
  };
98
99
  /**
99
100
  * Structured indexing configuration.
@@ -107,6 +108,15 @@ export type TypeInfoORMIndexingConfig = {
107
108
  * Optional writer for structured indexing.
108
109
  */
109
110
  writer?: StructuredWriter;
111
+ /**
112
+ * Explicitly indexed field names by type. Fields not listed are excluded
113
+ * from structured indexing and structured query routing.
114
+ */
115
+ indexedFieldsByType?: Record<string, string[]>;
116
+ /**
117
+ * Optional tokenizer overrides for structured string contains/LIKE behavior.
118
+ */
119
+ tokenizer?: Partial<StructuredStringTokenizerConfig>;
110
120
  /**
111
121
  * Field name mapping per type.
112
122
  */
@@ -137,6 +147,29 @@ export type TypeInfoORMIndexingConfig = {
137
147
  * Optional search limits for indexing queries.
138
148
  */
139
149
  limits?: ResolvedSearchLimits;
150
+ /**
151
+ * Optional observability hooks for indexing/routing diagnostics.
152
+ */
153
+ observability?: {
154
+ /**
155
+ * Called when list routing chooses a query execution path.
156
+ */
157
+ onListRoutingDecision?: (event: {
158
+ typeName: string;
159
+ path: "fullText" | "structured" | "fullScanCompare";
160
+ reason: "fullTextPlan" | "structuredEligible" | "criteriaWithoutIndexedPath" | "indexedPathFailedOrUnsupported";
161
+ criteriaCount: number;
162
+ }) => void;
163
+ /**
164
+ * Called when structured indexing writes/removes document entries.
165
+ */
166
+ onStructuredIndexWrite?: (event: {
167
+ typeName: string;
168
+ docId: string;
169
+ action: "upsert" | "remove";
170
+ indexedFieldCount: number;
171
+ }) => void;
172
+ };
140
173
  };
141
174
  /**
142
175
  * The basis for the configuration for the TypeInfoORMService.
@@ -187,6 +220,46 @@ export declare class TypeInfoORMService implements TypeInfoORMAPI {
187
220
  protected config: TypeInfoORMServiceConfig;
188
221
  protected dacRoleCache: Record<string, DACRole>;
189
222
  protected indexingRelationshipDriver?: IndexingRelationshipDriver;
223
+ /**
224
+ * Emit list routing decision observability events without impacting runtime behavior.
225
+ */
226
+ protected emitListRoutingDecision: (
227
+ /**
228
+ * Type being listed.
229
+ */
230
+ typeName: string,
231
+ /**
232
+ * Selected routing path.
233
+ */
234
+ path: "fullText" | "structured" | "fullScanCompare",
235
+ /**
236
+ * Why this path was selected.
237
+ */
238
+ reason: "fullTextPlan" | "structuredEligible" | "criteriaWithoutIndexedPath" | "indexedPathFailedOrUnsupported",
239
+ /**
240
+ * Number of criteria considered.
241
+ */
242
+ criteriaCount: number) => void;
243
+ /**
244
+ * Emit structured index write observability events without impacting behavior.
245
+ */
246
+ protected emitStructuredIndexWrite: (
247
+ /**
248
+ * Type being indexed.
249
+ */
250
+ typeName: string,
251
+ /**
252
+ * Indexed document id.
253
+ */
254
+ docId: string,
255
+ /**
256
+ * Structured indexing action.
257
+ */
258
+ action: "upsert" | "remove",
259
+ /**
260
+ * Number of indexed fields in the write payload.
261
+ */
262
+ indexedFieldCount: number) => void;
190
263
  /**
191
264
  * @param config ORM service configuration.
192
265
  */
@@ -267,17 +340,129 @@ export declare class TypeInfoORMService implements TypeInfoORMAPI {
267
340
  */
268
341
  protected getTypeInfo: (typeName: string) => TypeInfo;
269
342
  /**
270
- * @returns Resolved index field name, if available.
343
+ * @returns Resolved full-text index field names.
271
344
  */
272
- protected resolveFullTextIndexField: (
345
+ protected resolveFullTextIndexFields: (
273
346
  /**
274
- * Type name used to resolve the default index field.
347
+ * Type name used to resolve the default index field(s).
275
348
  */
276
349
  typeName: string,
277
350
  /**
278
351
  * Optional override for the index field.
279
352
  */
280
- override?: string) => string | undefined;
353
+ override?: string) => string[];
354
+ /**
355
+ * @returns True when the operator maps to full-text search.
356
+ */
357
+ protected isFullTextSearchOperator: (
358
+ /**
359
+ * Operator to evaluate.
360
+ */
361
+ operator: ComparisonOperators) => boolean;
362
+ /**
363
+ * @returns Explicitly indexed structured field names for a type.
364
+ */
365
+ protected resolveStructuredIndexedFields: (
366
+ /**
367
+ * Type name used to resolve indexed structured fields.
368
+ */
369
+ typeName: string) => Set<string>;
370
+ /**
371
+ * @returns True when the field type and operator can be served by structured indexing.
372
+ */
373
+ protected isStructuredOperatorSupportedForField: (
374
+ /**
375
+ * Field definition from TypeInfo.
376
+ */
377
+ field: TypeInfoField,
378
+ /**
379
+ * Search operator to evaluate.
380
+ */
381
+ operator: ComparisonOperators) => boolean;
382
+ /**
383
+ * @returns True when criteria can be evaluated using structured indexing.
384
+ */
385
+ protected canUseStructuredIndexForCriteria: (
386
+ /**
387
+ * Type being listed.
388
+ */
389
+ typeName: string,
390
+ /**
391
+ * Criteria to evaluate.
392
+ */
393
+ criteria?: SearchCriteria) => boolean;
394
+ /**
395
+ * @returns Full-text query plan derived from a field criterion.
396
+ */
397
+ protected toFullTextSearchPlan: (
398
+ /**
399
+ * Criterion to map.
400
+ */
401
+ criterion: FieldCriterion) => {
402
+ mode: "lossy" | "exact";
403
+ query: string;
404
+ } | undefined;
405
+ /**
406
+ * @returns Auto full-text search plan for list criteria, if applicable.
407
+ */
408
+ protected resolveAutoFullTextCriteriaPlan: (
409
+ /**
410
+ * Type being listed.
411
+ */
412
+ typeName: string,
413
+ /**
414
+ * Search criteria from list config.
415
+ */
416
+ criteria?: SearchCriteria) => {
417
+ mode: "lossy" | "exact";
418
+ query: string;
419
+ indexField: string;
420
+ } | undefined;
421
+ /**
422
+ * @returns Encoded cursor for full-scan compare pagination.
423
+ */
424
+ protected encodeFullScanCompareCursor: (
425
+ /**
426
+ * Next offset in filtered/sorted results.
427
+ */
428
+ offset: number) => string;
429
+ /**
430
+ * @returns Decoded offset for full-scan compare pagination.
431
+ */
432
+ protected decodeFullScanCompareCursor: (
433
+ /**
434
+ * Cursor from list config.
435
+ */
436
+ cursor?: string) => number;
437
+ /**
438
+ * Execute a criteria list via full scan + in-memory compare.
439
+ *
440
+ * This is the universal fallback strategy for criteria/operators that are not
441
+ * supported by indexed query planners.
442
+ *
443
+ * @returns List results with cursor.
444
+ */
445
+ protected listByFullScanAndCompare(
446
+ /**
447
+ * Type name to list.
448
+ */
449
+ typeName: string,
450
+ /**
451
+ * Original list config.
452
+ */
453
+ config: ListItemsConfig,
454
+ /**
455
+ * Selected fields for cleaned response.
456
+ */
457
+ cleanSelectedFields: (keyof TypeInfoDataItem)[] | undefined,
458
+ /**
459
+ * Whether DAC checks are enabled.
460
+ */
461
+ useDAC: boolean,
462
+ /**
463
+ * Optional request context.
464
+ */
465
+ context?: TypeInfoORMContext): Promise<ListItemsResults<Partial<TypeInfoDataItem>>>;
281
466
  /**
282
467
  * @param value Value to check.
283
468
  * @returns True when the value is a supported structured value.
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { SearchCriteria } from "../../../common/SearchTypes";
8
8
  import type { Where } from "../../Indexing/structured/Types";
9
+ import { type StructuredStringTokenizerConfig } from "../../Indexing/structured/StructuredStringLike";
9
10
  /**
10
11
  * Translate {@link SearchCriteria.fieldCriteria} into a structured WHERE tree.
11
12
  * @returns Structured where clause or undefined when no criteria exist.
@@ -14,4 +15,8 @@ export declare const criteriaToStructuredWhere: (
14
15
  /**
15
16
  * Search criteria to translate.
16
17
  */
17
- criteria?: SearchCriteria) => Where | undefined;
18
+ criteria?: SearchCriteria,
19
+ /**
20
+ * Optional tokenizer settings used to generate LIKE tokens.
21
+ */
22
+ tokenizer?: Partial<StructuredStringTokenizerConfig>) => Where | undefined;