@celerity-sdk/datastore 0.6.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.
@@ -78,57 +78,82 @@ function buildKeyConditionExpression(key, range) {
78
78
  }
79
79
  __name(buildKeyConditionExpression, "buildKeyConditionExpression");
80
80
  function buildFilterExpression(conditions) {
81
- const condArray = Array.isArray(conditions) ? conditions : [
82
- conditions
83
- ];
84
81
  const names = {};
85
82
  const values = {};
86
- const parts = [];
87
- let counter = 0;
88
- for (const cond of condArray) {
89
- const attrName = `#f${counter}`;
90
- names[attrName] = cond.name;
91
- switch (cond.operator) {
92
- case "eq":
93
- case "ne":
94
- case "lt":
95
- case "le":
96
- case "gt":
97
- case "ge": {
98
- const valKey = `:f${counter}`;
99
- values[valKey] = cond.value;
100
- parts.push(`${attrName} ${COMPARISON_OPERATORS[cond.operator]} ${valKey}`);
101
- break;
102
- }
103
- case "between": {
104
- const lowVal = `:f${counter}a`;
105
- const highVal = `:f${counter}b`;
106
- values[lowVal] = cond.low;
107
- values[highVal] = cond.high;
108
- parts.push(`${attrName} BETWEEN ${lowVal} AND ${highVal}`);
109
- break;
110
- }
111
- case "startsWith":
112
- case "contains": {
113
- const valKey = `:f${counter}`;
114
- values[valKey] = cond.value;
115
- const fnName = cond.operator === "startsWith" ? "begins_with" : "contains";
116
- parts.push(`${fnName}(${attrName}, ${valKey})`);
117
- break;
118
- }
119
- case "exists":
120
- parts.push(`attribute_exists(${attrName})`);
121
- break;
122
- }
123
- counter++;
124
- }
83
+ const counter = {
84
+ value: 0
85
+ };
86
+ const expression = buildExpressionNode(conditions, names, values, counter, 0);
125
87
  return {
126
- expression: parts.join(" AND "),
88
+ expression,
127
89
  names,
128
90
  values
129
91
  };
130
92
  }
131
93
  __name(buildFilterExpression, "buildFilterExpression");
94
+ function buildExpressionNode(expr, names, values, counter, depth) {
95
+ if (Array.isArray(expr)) {
96
+ return buildGroup(expr, "AND", names, values, counter, depth);
97
+ }
98
+ if (isOrGroup(expr)) {
99
+ return buildGroup(expr.or, "OR", names, values, counter, depth);
100
+ }
101
+ if (isAndGroup(expr)) {
102
+ return buildGroup(expr.and, "AND", names, values, counter, depth);
103
+ }
104
+ return buildSingleCondition(expr, names, values, counter);
105
+ }
106
+ __name(buildExpressionNode, "buildExpressionNode");
107
+ function buildGroup(children, operator, names, values, counter, depth) {
108
+ const parts = children.map((child) => buildExpressionNode(child, names, values, counter, depth + 1));
109
+ if (parts.length === 1) return parts[0];
110
+ const joined = parts.join(` ${operator} `);
111
+ return depth > 0 ? `(${joined})` : joined;
112
+ }
113
+ __name(buildGroup, "buildGroup");
114
+ function buildSingleCondition(cond, names, values, counter) {
115
+ const i = counter.value;
116
+ const attrName = `#f${i}`;
117
+ names[attrName] = cond.name;
118
+ counter.value++;
119
+ switch (cond.operator) {
120
+ case "eq":
121
+ case "ne":
122
+ case "lt":
123
+ case "le":
124
+ case "gt":
125
+ case "ge": {
126
+ const valKey = `:f${i}`;
127
+ values[valKey] = cond.value;
128
+ return `${attrName} ${COMPARISON_OPERATORS[cond.operator]} ${valKey}`;
129
+ }
130
+ case "between": {
131
+ const lowVal = `:f${i}a`;
132
+ const highVal = `:f${i}b`;
133
+ values[lowVal] = cond.low;
134
+ values[highVal] = cond.high;
135
+ return `${attrName} BETWEEN ${lowVal} AND ${highVal}`;
136
+ }
137
+ case "startsWith":
138
+ case "contains": {
139
+ const valKey = `:f${i}`;
140
+ values[valKey] = cond.value;
141
+ const fnName = cond.operator === "startsWith" ? "begins_with" : "contains";
142
+ return `${fnName}(${attrName}, ${valKey})`;
143
+ }
144
+ case "exists":
145
+ return `attribute_exists(${attrName})`;
146
+ }
147
+ }
148
+ __name(buildSingleCondition, "buildSingleCondition");
149
+ function isAndGroup(expr) {
150
+ return typeof expr === "object" && !Array.isArray(expr) && "and" in expr;
151
+ }
152
+ __name(isAndGroup, "isAndGroup");
153
+ function isOrGroup(expr) {
154
+ return typeof expr === "object" && !Array.isArray(expr) && "or" in expr;
155
+ }
156
+ __name(isOrGroup, "isOrGroup");
132
157
 
133
158
  // src/providers/dynamodb/dynamodb-item-listing.ts
134
159
  var debug = createDebug("celerity:datastore:dynamodb");
@@ -460,4 +485,4 @@ var DynamoDBDatastoreClient = class {
460
485
  export {
461
486
  DynamoDBDatastoreClient
462
487
  };
463
- //# sourceMappingURL=dynamodb-datastore-client-LQH3GS6X.js.map
488
+ //# sourceMappingURL=dynamodb-datastore-client-RLOVW5ZU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/dynamodb/dynamodb-datastore-client.ts","../src/providers/dynamodb/dynamodb-datastore.ts","../src/providers/dynamodb/dynamodb-item-listing.ts","../src/providers/dynamodb/expressions.ts","../src/providers/dynamodb/errors.ts"],"sourcesContent":["import { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";\nimport { DynamoDBDocumentClient } from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { DatastoreClient, Datastore } from \"../../types\";\nimport { DynamoDBDatastore } from \"./dynamodb-datastore\";\nimport type { DynamoDBDatastoreConfig } from \"./types\";\nimport { captureDynamoDBConfig } from \"./config\";\n\nexport class DynamoDBDatastoreClient implements DatastoreClient {\n private client: DynamoDBClient | null = null;\n private docClient: DynamoDBDocumentClient | null = null;\n private readonly config: DynamoDBDatastoreConfig;\n\n constructor(\n config?: DynamoDBDatastoreConfig,\n private readonly tracer?: CelerityTracer,\n ) {\n this.config = config ?? captureDynamoDBConfig();\n }\n\n datastore(name: string): Datastore {\n return new DynamoDBDatastore(name, this.getDocClient(), this.tracer);\n }\n\n close(): void {\n this.docClient?.destroy();\n this.client?.destroy();\n this.docClient = null;\n this.client = null;\n }\n\n private getDocClient(): DynamoDBDocumentClient {\n if (!this.docClient) {\n this.client = new DynamoDBClient({\n region: this.config.region,\n endpoint: this.config.endpoint,\n credentials: this.config.credentials,\n });\n this.docClient = DynamoDBDocumentClient.from(this.client, {\n marshallOptions: { removeUndefinedValues: true },\n });\n }\n return this.docClient;\n }\n}\n","import createDebug from \"debug\";\nimport {\n GetCommand,\n PutCommand,\n DeleteCommand,\n BatchGetCommand,\n BatchWriteCommand,\n type DynamoDBDocumentClient,\n} from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer, CeleritySpan } from \"@celerity-sdk/types\";\nimport type {\n Datastore,\n ItemKey,\n GetItemOptions,\n PutItemOptions,\n DeleteItemOptions,\n QueryOptions,\n ScanOptions,\n ItemListing,\n BatchGetItemsOptions,\n BatchGetResult,\n BatchWriteOperation,\n BatchWriteResult,\n} from \"../../types\";\nimport { DatastoreError, ConditionalCheckFailedError } from \"../../errors\";\nimport { DynamoDBItemListing } from \"./dynamodb-item-listing\";\nimport { buildFilterExpression } from \"./expressions\";\nimport { isConditionalCheckFailedError } from \"./errors\";\n\nconst debug = createDebug(\"celerity:datastore:dynamodb\");\n\nexport class DynamoDBDatastore implements Datastore {\n constructor(\n private readonly tableName: string,\n private readonly client: DynamoDBDocumentClient,\n private readonly tracer?: CelerityTracer,\n ) {}\n\n async getItem<T = Record<string, unknown>>(\n key: ItemKey,\n options?: GetItemOptions,\n ): Promise<T | null> {\n debug(\"getItem %s %o\", this.tableName, key);\n return this.traced(\n \"celerity.datastore.get_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const response = await this.client.send(\n new GetCommand({\n TableName: this.tableName,\n Key: key,\n ConsistentRead: options?.consistentRead,\n }),\n );\n return (response.Item as T) ?? null;\n } catch (error) {\n throw new DatastoreError(\n `Failed to get item from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async putItem(item: Record<string, unknown>, options?: PutItemOptions): Promise<void> {\n debug(\"putItem %s\", this.tableName);\n return this.traced(\n \"celerity.datastore.put_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const conditionParams = options?.condition\n ? buildFilterExpression(options.condition)\n : undefined;\n\n await this.client.send(\n new PutCommand({\n TableName: this.tableName,\n Item: item,\n ConditionExpression: conditionParams?.expression,\n ExpressionAttributeNames: conditionParams?.names,\n ExpressionAttributeValues: conditionParams?.values,\n }),\n );\n } catch (error) {\n if (isConditionalCheckFailedError(error)) {\n throw new ConditionalCheckFailedError(this.tableName, { cause: error });\n }\n throw new DatastoreError(\n `Failed to put item in table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async deleteItem(key: ItemKey, options?: DeleteItemOptions): Promise<void> {\n debug(\"deleteItem %s %o\", this.tableName, key);\n return this.traced(\n \"celerity.datastore.delete_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const conditionParams = options?.condition\n ? buildFilterExpression(options.condition)\n : undefined;\n\n await this.client.send(\n new DeleteCommand({\n TableName: this.tableName,\n Key: key,\n ConditionExpression: conditionParams?.expression,\n ExpressionAttributeNames: conditionParams?.names,\n ExpressionAttributeValues: conditionParams?.values,\n }),\n );\n } catch (error) {\n if (isConditionalCheckFailedError(error)) {\n throw new ConditionalCheckFailedError(this.tableName, { cause: error });\n }\n throw new DatastoreError(\n `Failed to delete item from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n query<T = Record<string, unknown>>(options: QueryOptions): ItemListing<T> {\n debug(\"query %s pk=%s\", this.tableName, options.key.name);\n return new DynamoDBItemListing<T>(this.client, this.tableName, \"query\", options, this.tracer);\n }\n\n scan<T = Record<string, unknown>>(options?: ScanOptions): ItemListing<T> {\n debug(\"scan %s\", this.tableName);\n return new DynamoDBItemListing<T>(\n this.client,\n this.tableName,\n \"scan\",\n options ?? {},\n this.tracer,\n );\n }\n\n async batchGetItems<T = Record<string, unknown>>(\n keys: ItemKey[],\n options?: BatchGetItemsOptions,\n ): Promise<BatchGetResult<T>> {\n debug(\"batchGetItems %s count=%d\", this.tableName, keys.length);\n return this.traced(\n \"celerity.datastore.batch_get_items\",\n { \"datastore.table\": this.tableName, \"datastore.batch_size\": keys.length },\n async () => {\n try {\n const response = await this.client.send(\n new BatchGetCommand({\n RequestItems: {\n [this.tableName]: {\n Keys: keys,\n ConsistentRead: options?.consistentRead,\n },\n },\n }),\n );\n\n const items = (response.Responses?.[this.tableName] ?? []) as T[];\n const unprocessedKeys = (response.UnprocessedKeys?.[this.tableName]?.Keys ??\n []) as ItemKey[];\n\n return { items, unprocessedKeys };\n } catch (error) {\n throw new DatastoreError(\n `Failed to batch get items from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async batchWriteItems(operations: BatchWriteOperation[]): Promise<BatchWriteResult> {\n debug(\"batchWriteItems %s count=%d\", this.tableName, operations.length);\n return this.traced(\n \"celerity.datastore.batch_write_items\",\n { \"datastore.table\": this.tableName, \"datastore.batch_size\": operations.length },\n async () => {\n try {\n const writeRequests = operations.map((op) => {\n if (op.type === \"put\") {\n return { PutRequest: { Item: op.item } };\n }\n return { DeleteRequest: { Key: op.key } };\n });\n\n const response = await this.client.send(\n new BatchWriteCommand({\n RequestItems: { [this.tableName]: writeRequests },\n }),\n );\n\n const unprocessedRequests = response.UnprocessedItems?.[this.tableName] ?? [];\n const unprocessedOperations: BatchWriteOperation[] = unprocessedRequests.map((req) => {\n if (req.PutRequest) {\n return { type: \"put\" as const, item: req.PutRequest.Item! };\n }\n return { type: \"delete\" as const, key: req.DeleteRequest!.Key! as ItemKey };\n });\n\n return { unprocessedOperations };\n } catch (error) {\n throw new DatastoreError(\n `Failed to batch write items to table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n private traced<T>(\n name: string,\n attributes: Record<string, string | number | boolean>,\n fn: (span?: CeleritySpan) => Promise<T>,\n ): Promise<T> {\n if (!this.tracer) return fn();\n return this.tracer.withSpan(name, (span) => fn(span), attributes);\n }\n}\n","import createDebug from \"debug\";\nimport { QueryCommand, ScanCommand, type DynamoDBDocumentClient } from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { ItemListing, QueryOptions, ScanOptions } from \"../../types\";\nimport { DatastoreError } from \"../../errors\";\nimport { buildKeyConditionExpression, buildFilterExpression } from \"./expressions\";\n\nconst debug = createDebug(\"celerity:datastore:dynamodb\");\n\ntype CursorState = {\n lastEvaluatedKey: Record<string, unknown>;\n};\n\nfunction encodeCursor(lastEvaluatedKey: Record<string, unknown>): string {\n const state: CursorState = { lastEvaluatedKey };\n return Buffer.from(JSON.stringify(state)).toString(\"base64url\");\n}\n\nfunction decodeCursor(cursor: string): CursorState {\n return JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\")) as CursorState;\n}\n\nexport class DynamoDBItemListing<T> implements ItemListing<T> {\n private _cursor: string | undefined;\n\n constructor(\n private readonly client: DynamoDBDocumentClient,\n private readonly tableName: string,\n private readonly mode: \"query\" | \"scan\",\n private readonly options: QueryOptions | ScanOptions,\n private readonly tracer?: CelerityTracer,\n ) {\n this._cursor = options.cursor;\n }\n\n get cursor(): string | undefined {\n return this._cursor;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n const cursorState = this._cursor ? decodeCursor(this._cursor) : undefined;\n let exclusiveStartKey: Record<string, unknown> | undefined = cursorState?.lastEvaluatedKey;\n\n do {\n debug(\"%s page %s key=%o\", this.mode, this.tableName, exclusiveStartKey ?? \"(start)\");\n\n const response = await this.fetchPage(exclusiveStartKey);\n\n for (const item of response.Items ?? []) {\n yield item as T;\n }\n\n exclusiveStartKey = response.LastEvaluatedKey as Record<string, unknown> | undefined;\n\n if (exclusiveStartKey) {\n this._cursor = encodeCursor(exclusiveStartKey);\n } else {\n this._cursor = undefined;\n }\n } while (exclusiveStartKey);\n }\n\n private async fetchPage(exclusiveStartKey?: Record<string, unknown>) {\n const command =\n this.mode === \"query\"\n ? this.buildQueryCommand(exclusiveStartKey)\n : this.buildScanCommand(exclusiveStartKey);\n\n const doFetch = async () => {\n try {\n return await this.client.send(command);\n } catch (error) {\n throw new DatastoreError(\n `Failed to ${this.mode} table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n };\n\n if (!this.tracer) return doFetch();\n return this.tracer.withSpan(`celerity.datastore.${this.mode}_page`, () => doFetch(), {\n \"datastore.table\": this.tableName,\n });\n }\n\n private buildQueryCommand(exclusiveStartKey?: Record<string, unknown>) {\n const opts = this.options as QueryOptions;\n const keyExpr = buildKeyConditionExpression(opts.key, opts.range);\n\n const filterExpr = opts.filter ? buildFilterExpression(opts.filter) : undefined;\n\n return new QueryCommand({\n TableName: this.tableName,\n IndexName: opts.indexName,\n KeyConditionExpression: keyExpr.expression,\n FilterExpression: filterExpr?.expression,\n ExpressionAttributeNames: { ...keyExpr.names, ...filterExpr?.names },\n ExpressionAttributeValues: { ...keyExpr.values, ...filterExpr?.values },\n ScanIndexForward: opts.sortAscending,\n Limit: opts.maxResults,\n ExclusiveStartKey: exclusiveStartKey,\n ConsistentRead: opts.consistentRead,\n });\n }\n\n private buildScanCommand(exclusiveStartKey?: Record<string, unknown>) {\n const opts = this.options as ScanOptions;\n\n const filterExpr = opts.filter ? buildFilterExpression(opts.filter) : undefined;\n\n return new ScanCommand({\n TableName: this.tableName,\n IndexName: opts.indexName,\n FilterExpression: filterExpr?.expression,\n ExpressionAttributeNames:\n filterExpr?.names && Object.keys(filterExpr.names).length > 0\n ? filterExpr.names\n : undefined,\n ExpressionAttributeValues:\n filterExpr?.values && Object.keys(filterExpr.values).length > 0\n ? filterExpr.values\n : undefined,\n Limit: opts.maxResults,\n ExclusiveStartKey: exclusiveStartKey,\n ConsistentRead: opts.consistentRead,\n });\n }\n}\n","import type {\n Condition,\n KeyCondition,\n RangeCondition,\n ConditionExpression,\n AndGroup,\n OrGroup,\n} from \"../../types\";\n\nexport type ExpressionResult = {\n expression: string;\n names: Record<string, string>;\n values: Record<string, unknown>;\n};\n\nconst COMPARISON_OPERATORS = {\n eq: \"=\",\n ne: \"<>\",\n lt: \"<\",\n le: \"<=\",\n gt: \">\",\n ge: \">=\",\n} as const;\n\n/**\n * Builds a DynamoDB KeyConditionExpression from a key condition and optional range condition.\n * Uses `#k`/`:k` prefixed placeholders to avoid collision with filter placeholders.\n */\nexport function buildKeyConditionExpression(\n key: KeyCondition,\n range?: RangeCondition,\n): ExpressionResult {\n const names: Record<string, string> = {};\n const values: Record<string, unknown> = {};\n let counter = 0;\n\n const pkName = `#k${counter}`;\n const pkValue = `:k${counter}`;\n names[pkName] = key.name;\n values[pkValue] = key.value;\n counter++;\n\n let expression = `${pkName} = ${pkValue}`;\n\n if (range) {\n const skName = `#k${counter}`;\n names[skName] = range.name;\n\n switch (range.operator) {\n case \"eq\":\n case \"lt\":\n case \"le\":\n case \"gt\":\n case \"ge\": {\n const skValue = `:k${counter}`;\n values[skValue] = range.value;\n expression += ` AND ${skName} ${COMPARISON_OPERATORS[range.operator]} ${skValue}`;\n break;\n }\n case \"between\": {\n const lowVal = `:k${counter}a`;\n const highVal = `:k${counter}b`;\n values[lowVal] = range.low;\n values[highVal] = range.high;\n expression += ` AND ${skName} BETWEEN ${lowVal} AND ${highVal}`;\n break;\n }\n case \"startsWith\": {\n const skValue = `:k${counter}`;\n values[skValue] = range.value;\n expression += ` AND begins_with(${skName}, ${skValue})`;\n break;\n }\n }\n }\n\n return { expression, names, values };\n}\n\ntype MutableCounter = { value: number };\n\n/**\n * Builds a DynamoDB FilterExpression (or ConditionExpression for writes)\n * from a condition expression tree. Supports single conditions, arrays of\n * conditions (implicit AND), and explicit AND/OR groups with recursive nesting.\n * Uses `#f`/`:f` prefixed placeholders to avoid collision with key placeholders.\n */\nexport function buildFilterExpression(conditions: ConditionExpression): ExpressionResult {\n const names: Record<string, string> = {};\n const values: Record<string, unknown> = {};\n const counter: MutableCounter = { value: 0 };\n\n const expression = buildExpressionNode(conditions, names, values, counter, 0);\n return { expression, names, values };\n}\n\nfunction buildExpressionNode(\n expr: ConditionExpression,\n names: Record<string, string>,\n values: Record<string, unknown>,\n counter: MutableCounter,\n depth: number,\n): string {\n if (Array.isArray(expr)) {\n return buildGroup(expr, \"AND\", names, values, counter, depth);\n }\n if (isOrGroup(expr)) {\n return buildGroup(expr.or, \"OR\", names, values, counter, depth);\n }\n if (isAndGroup(expr)) {\n return buildGroup(expr.and, \"AND\", names, values, counter, depth);\n }\n return buildSingleCondition(expr, names, values, counter);\n}\n\nfunction buildGroup(\n children: ConditionExpression[],\n operator: \"AND\" | \"OR\",\n names: Record<string, string>,\n values: Record<string, unknown>,\n counter: MutableCounter,\n depth: number,\n): string {\n const parts = children.map((child) =>\n buildExpressionNode(child, names, values, counter, depth + 1),\n );\n\n if (parts.length === 1) return parts[0];\n\n const joined = parts.join(` ${operator} `);\n return depth > 0 ? `(${joined})` : joined;\n}\n\nfunction buildSingleCondition(\n cond: Condition,\n names: Record<string, string>,\n values: Record<string, unknown>,\n counter: MutableCounter,\n): string {\n const i = counter.value;\n const attrName = `#f${i}`;\n names[attrName] = cond.name;\n counter.value++;\n\n switch (cond.operator) {\n case \"eq\":\n case \"ne\":\n case \"lt\":\n case \"le\":\n case \"gt\":\n case \"ge\": {\n const valKey = `:f${i}`;\n values[valKey] = cond.value;\n return `${attrName} ${COMPARISON_OPERATORS[cond.operator]} ${valKey}`;\n }\n case \"between\": {\n const lowVal = `:f${i}a`;\n const highVal = `:f${i}b`;\n values[lowVal] = cond.low;\n values[highVal] = cond.high;\n return `${attrName} BETWEEN ${lowVal} AND ${highVal}`;\n }\n case \"startsWith\":\n case \"contains\": {\n const valKey = `:f${i}`;\n values[valKey] = cond.value;\n const fnName = cond.operator === \"startsWith\" ? \"begins_with\" : \"contains\";\n return `${fnName}(${attrName}, ${valKey})`;\n }\n case \"exists\":\n return `attribute_exists(${attrName})`;\n }\n}\n\nfunction isAndGroup(expr: ConditionExpression): expr is AndGroup {\n return typeof expr === \"object\" && !Array.isArray(expr) && \"and\" in expr;\n}\n\nfunction isOrGroup(expr: ConditionExpression): expr is OrGroup {\n return typeof expr === \"object\" && !Array.isArray(expr) && \"or\" in expr;\n}\n","/**\n * Checks if an error is a DynamoDB ConditionalCheckFailedException.\n */\nexport function isConditionalCheckFailedError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n return (error as { name?: string }).name === \"ConditionalCheckFailedException\";\n}\n"],"mappings":"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","names":["DynamoDBClient","DynamoDBDocumentClient","createDebug","GetCommand","PutCommand","DeleteCommand","BatchGetCommand","BatchWriteCommand","createDebug","QueryCommand","ScanCommand","COMPARISON_OPERATORS","eq","ne","lt","le","gt","ge","buildKeyConditionExpression","key","range","names","values","counter","pkName","pkValue","name","value","expression","skName","operator","skValue","lowVal","highVal","low","high","buildFilterExpression","conditions","buildExpressionNode","expr","depth","Array","isArray","buildGroup","isOrGroup","or","isAndGroup","and","buildSingleCondition","children","parts","map","child","length","joined","join","cond","i","attrName","valKey","fnName","debug","createDebug","encodeCursor","lastEvaluatedKey","state","Buffer","from","JSON","stringify","toString","decodeCursor","cursor","parse","DynamoDBItemListing","_cursor","client","tableName","mode","options","tracer","Symbol","asyncIterator","cursorState","undefined","exclusiveStartKey","response","fetchPage","item","Items","LastEvaluatedKey","command","buildQueryCommand","buildScanCommand","doFetch","send","error","DatastoreError","cause","withSpan","opts","keyExpr","buildKeyConditionExpression","key","range","filterExpr","filter","buildFilterExpression","QueryCommand","TableName","IndexName","indexName","KeyConditionExpression","expression","FilterExpression","ExpressionAttributeNames","names","ExpressionAttributeValues","values","ScanIndexForward","sortAscending","Limit","maxResults","ExclusiveStartKey","ConsistentRead","consistentRead","ScanCommand","Object","keys","length","isConditionalCheckFailedError","error","Error","name","debug","createDebug","DynamoDBDatastore","tableName","client","tracer","getItem","key","options","traced","response","send","GetCommand","TableName","Key","ConsistentRead","consistentRead","Item","error","DatastoreError","cause","putItem","item","conditionParams","condition","buildFilterExpression","undefined","PutCommand","ConditionExpression","expression","ExpressionAttributeNames","names","ExpressionAttributeValues","values","isConditionalCheckFailedError","ConditionalCheckFailedError","deleteItem","DeleteCommand","query","name","DynamoDBItemListing","scan","batchGetItems","keys","length","BatchGetCommand","RequestItems","Keys","items","Responses","unprocessedKeys","UnprocessedKeys","batchWriteItems","operations","writeRequests","map","op","type","PutRequest","DeleteRequest","BatchWriteCommand","unprocessedRequests","UnprocessedItems","unprocessedOperations","req","attributes","fn","withSpan","span","DynamoDBDatastoreClient","client","docClient","config","tracer","captureDynamoDBConfig","datastore","name","DynamoDBDatastore","getDocClient","close","destroy","DynamoDBClient","region","endpoint","credentials","DynamoDBDocumentClient","from","marshallOptions","removeUndefinedValues"]}
package/dist/index.cjs CHANGED
@@ -106,56 +106,76 @@ function buildKeyConditionExpression(key, range) {
106
106
  };
107
107
  }
108
108
  function buildFilterExpression(conditions) {
109
- const condArray = Array.isArray(conditions) ? conditions : [
110
- conditions
111
- ];
112
109
  const names = {};
113
110
  const values = {};
114
- const parts = [];
115
- let counter = 0;
116
- for (const cond of condArray) {
117
- const attrName = `#f${counter}`;
118
- names[attrName] = cond.name;
119
- switch (cond.operator) {
120
- case "eq":
121
- case "ne":
122
- case "lt":
123
- case "le":
124
- case "gt":
125
- case "ge": {
126
- const valKey = `:f${counter}`;
127
- values[valKey] = cond.value;
128
- parts.push(`${attrName} ${COMPARISON_OPERATORS[cond.operator]} ${valKey}`);
129
- break;
130
- }
131
- case "between": {
132
- const lowVal = `:f${counter}a`;
133
- const highVal = `:f${counter}b`;
134
- values[lowVal] = cond.low;
135
- values[highVal] = cond.high;
136
- parts.push(`${attrName} BETWEEN ${lowVal} AND ${highVal}`);
137
- break;
138
- }
139
- case "startsWith":
140
- case "contains": {
141
- const valKey = `:f${counter}`;
142
- values[valKey] = cond.value;
143
- const fnName = cond.operator === "startsWith" ? "begins_with" : "contains";
144
- parts.push(`${fnName}(${attrName}, ${valKey})`);
145
- break;
146
- }
147
- case "exists":
148
- parts.push(`attribute_exists(${attrName})`);
149
- break;
150
- }
151
- counter++;
152
- }
111
+ const counter = {
112
+ value: 0
113
+ };
114
+ const expression = buildExpressionNode(conditions, names, values, counter, 0);
153
115
  return {
154
- expression: parts.join(" AND "),
116
+ expression,
155
117
  names,
156
118
  values
157
119
  };
158
120
  }
121
+ function buildExpressionNode(expr, names, values, counter, depth) {
122
+ if (Array.isArray(expr)) {
123
+ return buildGroup(expr, "AND", names, values, counter, depth);
124
+ }
125
+ if (isOrGroup(expr)) {
126
+ return buildGroup(expr.or, "OR", names, values, counter, depth);
127
+ }
128
+ if (isAndGroup(expr)) {
129
+ return buildGroup(expr.and, "AND", names, values, counter, depth);
130
+ }
131
+ return buildSingleCondition(expr, names, values, counter);
132
+ }
133
+ function buildGroup(children, operator, names, values, counter, depth) {
134
+ const parts = children.map((child) => buildExpressionNode(child, names, values, counter, depth + 1));
135
+ if (parts.length === 1) return parts[0];
136
+ const joined = parts.join(` ${operator} `);
137
+ return depth > 0 ? `(${joined})` : joined;
138
+ }
139
+ function buildSingleCondition(cond, names, values, counter) {
140
+ const i = counter.value;
141
+ const attrName = `#f${i}`;
142
+ names[attrName] = cond.name;
143
+ counter.value++;
144
+ switch (cond.operator) {
145
+ case "eq":
146
+ case "ne":
147
+ case "lt":
148
+ case "le":
149
+ case "gt":
150
+ case "ge": {
151
+ const valKey = `:f${i}`;
152
+ values[valKey] = cond.value;
153
+ return `${attrName} ${COMPARISON_OPERATORS[cond.operator]} ${valKey}`;
154
+ }
155
+ case "between": {
156
+ const lowVal = `:f${i}a`;
157
+ const highVal = `:f${i}b`;
158
+ values[lowVal] = cond.low;
159
+ values[highVal] = cond.high;
160
+ return `${attrName} BETWEEN ${lowVal} AND ${highVal}`;
161
+ }
162
+ case "startsWith":
163
+ case "contains": {
164
+ const valKey = `:f${i}`;
165
+ values[valKey] = cond.value;
166
+ const fnName = cond.operator === "startsWith" ? "begins_with" : "contains";
167
+ return `${fnName}(${attrName}, ${valKey})`;
168
+ }
169
+ case "exists":
170
+ return `attribute_exists(${attrName})`;
171
+ }
172
+ }
173
+ function isAndGroup(expr) {
174
+ return typeof expr === "object" && !Array.isArray(expr) && "and" in expr;
175
+ }
176
+ function isOrGroup(expr) {
177
+ return typeof expr === "object" && !Array.isArray(expr) && "or" in expr;
178
+ }
159
179
  var COMPARISON_OPERATORS;
160
180
  var init_expressions = __esm({
161
181
  "src/providers/dynamodb/expressions.ts"() {
@@ -170,6 +190,11 @@ var init_expressions = __esm({
170
190
  };
171
191
  __name(buildKeyConditionExpression, "buildKeyConditionExpression");
172
192
  __name(buildFilterExpression, "buildFilterExpression");
193
+ __name(buildExpressionNode, "buildExpressionNode");
194
+ __name(buildGroup, "buildGroup");
195
+ __name(buildSingleCondition, "buildSingleCondition");
196
+ __name(isAndGroup, "isAndGroup");
197
+ __name(isOrGroup, "isOrGroup");
173
198
  }
174
199
  });
175
200
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/providers/dynamodb/expressions.ts","../src/providers/dynamodb/dynamodb-item-listing.ts","../src/providers/dynamodb/errors.ts","../src/providers/dynamodb/dynamodb-datastore.ts","../src/providers/dynamodb/config.ts","../src/providers/dynamodb/dynamodb-datastore-client.ts","../src/index.ts","../src/types.ts","../src/factory.ts","../src/decorators.ts","../src/helpers.ts","../src/layer.ts"],"sourcesContent":["export class DatastoreError extends Error {\n constructor(\n message: string,\n public readonly table: string,\n options?: { cause?: unknown },\n ) {\n super(message, options);\n this.name = \"DatastoreError\";\n }\n}\n\nexport class ConditionalCheckFailedError extends DatastoreError {\n constructor(table: string, options?: { cause?: unknown }) {\n super(`Conditional check failed on table \"${table}\"`, table, options);\n this.name = \"ConditionalCheckFailedError\";\n }\n}\n","import type { KeyCondition, RangeCondition, ConditionExpression } from \"../../types\";\n\nexport type ExpressionResult = {\n expression: string;\n names: Record<string, string>;\n values: Record<string, unknown>;\n};\n\nconst COMPARISON_OPERATORS = {\n eq: \"=\",\n ne: \"<>\",\n lt: \"<\",\n le: \"<=\",\n gt: \">\",\n ge: \">=\",\n} as const;\n\n/**\n * Builds a DynamoDB KeyConditionExpression from a key condition and optional range condition.\n * Uses `#k`/`:k` prefixed placeholders to avoid collision with filter placeholders.\n */\nexport function buildKeyConditionExpression(\n key: KeyCondition,\n range?: RangeCondition,\n): ExpressionResult {\n const names: Record<string, string> = {};\n const values: Record<string, unknown> = {};\n let counter = 0;\n\n const pkName = `#k${counter}`;\n const pkValue = `:k${counter}`;\n names[pkName] = key.name;\n values[pkValue] = key.value;\n counter++;\n\n let expression = `${pkName} = ${pkValue}`;\n\n if (range) {\n const skName = `#k${counter}`;\n names[skName] = range.name;\n\n switch (range.operator) {\n case \"eq\":\n case \"lt\":\n case \"le\":\n case \"gt\":\n case \"ge\": {\n const skValue = `:k${counter}`;\n values[skValue] = range.value;\n expression += ` AND ${skName} ${COMPARISON_OPERATORS[range.operator]} ${skValue}`;\n break;\n }\n case \"between\": {\n const lowVal = `:k${counter}a`;\n const highVal = `:k${counter}b`;\n values[lowVal] = range.low;\n values[highVal] = range.high;\n expression += ` AND ${skName} BETWEEN ${lowVal} AND ${highVal}`;\n break;\n }\n case \"startsWith\": {\n const skValue = `:k${counter}`;\n values[skValue] = range.value;\n expression += ` AND begins_with(${skName}, ${skValue})`;\n break;\n }\n }\n }\n\n return { expression, names, values };\n}\n\n/**\n * Builds a DynamoDB FilterExpression (or ConditionExpression for writes)\n * from one or more Condition objects. Conditions are AND'd together.\n * Uses `#f`/`:f` prefixed placeholders to avoid collision with key placeholders.\n */\nexport function buildFilterExpression(conditions: ConditionExpression): ExpressionResult {\n const condArray = Array.isArray(conditions) ? conditions : [conditions];\n const names: Record<string, string> = {};\n const values: Record<string, unknown> = {};\n const parts: string[] = [];\n let counter = 0;\n\n for (const cond of condArray) {\n const attrName = `#f${counter}`;\n names[attrName] = cond.name;\n\n switch (cond.operator) {\n case \"eq\":\n case \"ne\":\n case \"lt\":\n case \"le\":\n case \"gt\":\n case \"ge\": {\n const valKey = `:f${counter}`;\n values[valKey] = cond.value;\n parts.push(`${attrName} ${COMPARISON_OPERATORS[cond.operator]} ${valKey}`);\n break;\n }\n case \"between\": {\n const lowVal = `:f${counter}a`;\n const highVal = `:f${counter}b`;\n values[lowVal] = cond.low;\n values[highVal] = cond.high;\n parts.push(`${attrName} BETWEEN ${lowVal} AND ${highVal}`);\n break;\n }\n case \"startsWith\":\n case \"contains\": {\n const valKey = `:f${counter}`;\n values[valKey] = cond.value;\n const fnName = cond.operator === \"startsWith\" ? \"begins_with\" : \"contains\";\n parts.push(`${fnName}(${attrName}, ${valKey})`);\n break;\n }\n case \"exists\":\n parts.push(`attribute_exists(${attrName})`);\n break;\n }\n\n counter++;\n }\n\n return { expression: parts.join(\" AND \"), names, values };\n}\n","import createDebug from \"debug\";\nimport { QueryCommand, ScanCommand, type DynamoDBDocumentClient } from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { ItemListing, QueryOptions, ScanOptions } from \"../../types\";\nimport { DatastoreError } from \"../../errors\";\nimport { buildKeyConditionExpression, buildFilterExpression } from \"./expressions\";\n\nconst debug = createDebug(\"celerity:datastore:dynamodb\");\n\ntype CursorState = {\n lastEvaluatedKey: Record<string, unknown>;\n};\n\nfunction encodeCursor(lastEvaluatedKey: Record<string, unknown>): string {\n const state: CursorState = { lastEvaluatedKey };\n return Buffer.from(JSON.stringify(state)).toString(\"base64url\");\n}\n\nfunction decodeCursor(cursor: string): CursorState {\n return JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\")) as CursorState;\n}\n\nexport class DynamoDBItemListing<T> implements ItemListing<T> {\n private _cursor: string | undefined;\n\n constructor(\n private readonly client: DynamoDBDocumentClient,\n private readonly tableName: string,\n private readonly mode: \"query\" | \"scan\",\n private readonly options: QueryOptions | ScanOptions,\n private readonly tracer?: CelerityTracer,\n ) {\n this._cursor = options.cursor;\n }\n\n get cursor(): string | undefined {\n return this._cursor;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n const cursorState = this._cursor ? decodeCursor(this._cursor) : undefined;\n let exclusiveStartKey: Record<string, unknown> | undefined = cursorState?.lastEvaluatedKey;\n\n do {\n debug(\"%s page %s key=%o\", this.mode, this.tableName, exclusiveStartKey ?? \"(start)\");\n\n const response = await this.fetchPage(exclusiveStartKey);\n\n for (const item of response.Items ?? []) {\n yield item as T;\n }\n\n exclusiveStartKey = response.LastEvaluatedKey as Record<string, unknown> | undefined;\n\n if (exclusiveStartKey) {\n this._cursor = encodeCursor(exclusiveStartKey);\n } else {\n this._cursor = undefined;\n }\n } while (exclusiveStartKey);\n }\n\n private async fetchPage(exclusiveStartKey?: Record<string, unknown>) {\n const command =\n this.mode === \"query\"\n ? this.buildQueryCommand(exclusiveStartKey)\n : this.buildScanCommand(exclusiveStartKey);\n\n const doFetch = async () => {\n try {\n return await this.client.send(command);\n } catch (error) {\n throw new DatastoreError(\n `Failed to ${this.mode} table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n };\n\n if (!this.tracer) return doFetch();\n return this.tracer.withSpan(`celerity.datastore.${this.mode}_page`, () => doFetch(), {\n \"datastore.table\": this.tableName,\n });\n }\n\n private buildQueryCommand(exclusiveStartKey?: Record<string, unknown>) {\n const opts = this.options as QueryOptions;\n const keyExpr = buildKeyConditionExpression(opts.key, opts.range);\n\n const filterExpr = opts.filter ? buildFilterExpression(opts.filter) : undefined;\n\n return new QueryCommand({\n TableName: this.tableName,\n IndexName: opts.indexName,\n KeyConditionExpression: keyExpr.expression,\n FilterExpression: filterExpr?.expression,\n ExpressionAttributeNames: { ...keyExpr.names, ...filterExpr?.names },\n ExpressionAttributeValues: { ...keyExpr.values, ...filterExpr?.values },\n ScanIndexForward: opts.sortAscending,\n Limit: opts.maxResults,\n ExclusiveStartKey: exclusiveStartKey,\n ConsistentRead: opts.consistentRead,\n });\n }\n\n private buildScanCommand(exclusiveStartKey?: Record<string, unknown>) {\n const opts = this.options as ScanOptions;\n\n const filterExpr = opts.filter ? buildFilterExpression(opts.filter) : undefined;\n\n return new ScanCommand({\n TableName: this.tableName,\n IndexName: opts.indexName,\n FilterExpression: filterExpr?.expression,\n ExpressionAttributeNames:\n filterExpr?.names && Object.keys(filterExpr.names).length > 0\n ? filterExpr.names\n : undefined,\n ExpressionAttributeValues:\n filterExpr?.values && Object.keys(filterExpr.values).length > 0\n ? filterExpr.values\n : undefined,\n Limit: opts.maxResults,\n ExclusiveStartKey: exclusiveStartKey,\n ConsistentRead: opts.consistentRead,\n });\n }\n}\n","/**\n * Checks if an error is a DynamoDB ConditionalCheckFailedException.\n */\nexport function isConditionalCheckFailedError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n return (error as { name?: string }).name === \"ConditionalCheckFailedException\";\n}\n","import createDebug from \"debug\";\nimport {\n GetCommand,\n PutCommand,\n DeleteCommand,\n BatchGetCommand,\n BatchWriteCommand,\n type DynamoDBDocumentClient,\n} from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer, CeleritySpan } from \"@celerity-sdk/types\";\nimport type {\n Datastore,\n ItemKey,\n GetItemOptions,\n PutItemOptions,\n DeleteItemOptions,\n QueryOptions,\n ScanOptions,\n ItemListing,\n BatchGetItemsOptions,\n BatchGetResult,\n BatchWriteOperation,\n BatchWriteResult,\n} from \"../../types\";\nimport { DatastoreError, ConditionalCheckFailedError } from \"../../errors\";\nimport { DynamoDBItemListing } from \"./dynamodb-item-listing\";\nimport { buildFilterExpression } from \"./expressions\";\nimport { isConditionalCheckFailedError } from \"./errors\";\n\nconst debug = createDebug(\"celerity:datastore:dynamodb\");\n\nexport class DynamoDBDatastore implements Datastore {\n constructor(\n private readonly tableName: string,\n private readonly client: DynamoDBDocumentClient,\n private readonly tracer?: CelerityTracer,\n ) {}\n\n async getItem<T = Record<string, unknown>>(\n key: ItemKey,\n options?: GetItemOptions,\n ): Promise<T | null> {\n debug(\"getItem %s %o\", this.tableName, key);\n return this.traced(\n \"celerity.datastore.get_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const response = await this.client.send(\n new GetCommand({\n TableName: this.tableName,\n Key: key,\n ConsistentRead: options?.consistentRead,\n }),\n );\n return (response.Item as T) ?? null;\n } catch (error) {\n throw new DatastoreError(\n `Failed to get item from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async putItem(item: Record<string, unknown>, options?: PutItemOptions): Promise<void> {\n debug(\"putItem %s\", this.tableName);\n return this.traced(\n \"celerity.datastore.put_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const conditionParams = options?.condition\n ? buildFilterExpression(options.condition)\n : undefined;\n\n await this.client.send(\n new PutCommand({\n TableName: this.tableName,\n Item: item,\n ConditionExpression: conditionParams?.expression,\n ExpressionAttributeNames: conditionParams?.names,\n ExpressionAttributeValues: conditionParams?.values,\n }),\n );\n } catch (error) {\n if (isConditionalCheckFailedError(error)) {\n throw new ConditionalCheckFailedError(this.tableName, { cause: error });\n }\n throw new DatastoreError(\n `Failed to put item in table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async deleteItem(key: ItemKey, options?: DeleteItemOptions): Promise<void> {\n debug(\"deleteItem %s %o\", this.tableName, key);\n return this.traced(\n \"celerity.datastore.delete_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const conditionParams = options?.condition\n ? buildFilterExpression(options.condition)\n : undefined;\n\n await this.client.send(\n new DeleteCommand({\n TableName: this.tableName,\n Key: key,\n ConditionExpression: conditionParams?.expression,\n ExpressionAttributeNames: conditionParams?.names,\n ExpressionAttributeValues: conditionParams?.values,\n }),\n );\n } catch (error) {\n if (isConditionalCheckFailedError(error)) {\n throw new ConditionalCheckFailedError(this.tableName, { cause: error });\n }\n throw new DatastoreError(\n `Failed to delete item from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n query<T = Record<string, unknown>>(options: QueryOptions): ItemListing<T> {\n debug(\"query %s pk=%s\", this.tableName, options.key.name);\n return new DynamoDBItemListing<T>(this.client, this.tableName, \"query\", options, this.tracer);\n }\n\n scan<T = Record<string, unknown>>(options?: ScanOptions): ItemListing<T> {\n debug(\"scan %s\", this.tableName);\n return new DynamoDBItemListing<T>(\n this.client,\n this.tableName,\n \"scan\",\n options ?? {},\n this.tracer,\n );\n }\n\n async batchGetItems<T = Record<string, unknown>>(\n keys: ItemKey[],\n options?: BatchGetItemsOptions,\n ): Promise<BatchGetResult<T>> {\n debug(\"batchGetItems %s count=%d\", this.tableName, keys.length);\n return this.traced(\n \"celerity.datastore.batch_get_items\",\n { \"datastore.table\": this.tableName, \"datastore.batch_size\": keys.length },\n async () => {\n try {\n const response = await this.client.send(\n new BatchGetCommand({\n RequestItems: {\n [this.tableName]: {\n Keys: keys,\n ConsistentRead: options?.consistentRead,\n },\n },\n }),\n );\n\n const items = (response.Responses?.[this.tableName] ?? []) as T[];\n const unprocessedKeys = (response.UnprocessedKeys?.[this.tableName]?.Keys ??\n []) as ItemKey[];\n\n return { items, unprocessedKeys };\n } catch (error) {\n throw new DatastoreError(\n `Failed to batch get items from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async batchWriteItems(operations: BatchWriteOperation[]): Promise<BatchWriteResult> {\n debug(\"batchWriteItems %s count=%d\", this.tableName, operations.length);\n return this.traced(\n \"celerity.datastore.batch_write_items\",\n { \"datastore.table\": this.tableName, \"datastore.batch_size\": operations.length },\n async () => {\n try {\n const writeRequests = operations.map((op) => {\n if (op.type === \"put\") {\n return { PutRequest: { Item: op.item } };\n }\n return { DeleteRequest: { Key: op.key } };\n });\n\n const response = await this.client.send(\n new BatchWriteCommand({\n RequestItems: { [this.tableName]: writeRequests },\n }),\n );\n\n const unprocessedRequests = response.UnprocessedItems?.[this.tableName] ?? [];\n const unprocessedOperations: BatchWriteOperation[] = unprocessedRequests.map((req) => {\n if (req.PutRequest) {\n return { type: \"put\" as const, item: req.PutRequest.Item! };\n }\n return { type: \"delete\" as const, key: req.DeleteRequest!.Key! as ItemKey };\n });\n\n return { unprocessedOperations };\n } catch (error) {\n throw new DatastoreError(\n `Failed to batch write items to table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n private traced<T>(\n name: string,\n attributes: Record<string, string | number | boolean>,\n fn: (span?: CeleritySpan) => Promise<T>,\n ): Promise<T> {\n if (!this.tracer) return fn();\n return this.tracer.withSpan(name, (span) => fn(span), attributes);\n }\n}\n","import type { DynamoDBDatastoreConfig } from \"./types\";\n\n/**\n * Captures DynamoDB configuration from environment variables.\n * This is the only place that reads `process.env` for DynamoDB config.\n */\nexport function captureDynamoDBConfig(): DynamoDBDatastoreConfig {\n return {\n region: process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION,\n endpoint: process.env.CELERITY_AWS_DYNAMODB_ENDPOINT ?? process.env.AWS_ENDPOINT_URL,\n credentials:\n process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY\n ? {\n accessKeyId: process.env.AWS_ACCESS_KEY_ID,\n secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\n }\n : undefined,\n };\n}\n","import { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";\nimport { DynamoDBDocumentClient } from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { DatastoreClient, Datastore } from \"../../types\";\nimport { DynamoDBDatastore } from \"./dynamodb-datastore\";\nimport type { DynamoDBDatastoreConfig } from \"./types\";\nimport { captureDynamoDBConfig } from \"./config\";\n\nexport class DynamoDBDatastoreClient implements DatastoreClient {\n private client: DynamoDBClient | null = null;\n private docClient: DynamoDBDocumentClient | null = null;\n private readonly config: DynamoDBDatastoreConfig;\n\n constructor(\n config?: DynamoDBDatastoreConfig,\n private readonly tracer?: CelerityTracer,\n ) {\n this.config = config ?? captureDynamoDBConfig();\n }\n\n datastore(name: string): Datastore {\n return new DynamoDBDatastore(name, this.getDocClient(), this.tracer);\n }\n\n close(): void {\n this.docClient?.destroy();\n this.client?.destroy();\n this.docClient = null;\n this.client = null;\n }\n\n private getDocClient(): DynamoDBDocumentClient {\n if (!this.docClient) {\n this.client = new DynamoDBClient({\n region: this.config.region,\n endpoint: this.config.endpoint,\n credentials: this.config.credentials,\n });\n this.docClient = DynamoDBDocumentClient.from(this.client, {\n marshallOptions: { removeUndefinedValues: true },\n });\n }\n return this.docClient;\n }\n}\n","export {\n DatastoreClient,\n type ItemKey,\n type KeyCondition,\n type RangeCondition,\n type Condition,\n type ConditionExpression,\n type GetItemOptions,\n type PutItemOptions,\n type DeleteItemOptions,\n type QueryOptions,\n type ScanOptions,\n type ItemListing,\n type BatchGetItemsOptions,\n type BatchGetResult,\n type BatchWriteOperation,\n type BatchWriteResult,\n} from \"./types\";\n\nexport type { DynamoDBDatastoreConfig } from \"./providers/dynamodb/types\";\n\nexport { createDatastoreClient } from \"./factory\";\nexport type { CreateDatastoreClientOptions } from \"./factory\";\n\nexport { Datastore, datastoreToken, DEFAULT_DATASTORE_TOKEN } from \"./decorators\";\nexport { getDatastore } from \"./helpers\";\nexport { DatastoreLayer } from \"./layer\";\nexport { DatastoreError, ConditionalCheckFailedError } from \"./errors\";\n","import type { Closeable } from \"@celerity-sdk/types\";\n\nexport const DatastoreClient = Symbol.for(\"DatastoreClient\");\n\n/**\n * A data store client abstraction for NoSQL databases. Provides access to named\n * data stores (tables/collections), each representing a logical container for items.\n */\nexport interface DatastoreClient extends Closeable {\n /**\n * Retrieves a datastore instance by its logical name. The returned datastore\n * is a lightweight handle — no network calls are made until an operation is invoked.\n *\n * @param name The name of the datastore (table/collection).\n */\n datastore(name: string): Datastore;\n}\n\n/**\n * A datastore represents a logical container (table/collection) for items in a\n * NoSQL data store. It provides methods for performing CRUD operations, queries,\n * scans, and batch operations within the data store.\n */\nexport interface Datastore {\n /**\n * Retrieve an item from the data store by its primary key. Returns `null` if the\n * item does not exist.\n *\n * @param key The primary key attributes identifying the item.\n * @param options Optional parameters such as consistent read.\n * @returns A promise that resolves to the item, or `null` if not found.\n */\n getItem<T = Record<string, unknown>>(key: ItemKey, options?: GetItemOptions): Promise<T | null>;\n\n /**\n * Store an item in the data store. If an item with the same primary key already\n * exists, it is replaced entirely (upsert semantics).\n *\n * @param item The item to store. Must include all primary key attributes.\n * @param options Optional parameters such as condition expressions.\n */\n putItem(item: Record<string, unknown>, options?: PutItemOptions): Promise<void>;\n\n /**\n * Delete an item from the data store by its primary key. This operation is\n * idempotent — deleting a non-existent key does not throw.\n *\n * @param key The primary key attributes identifying the item to delete.\n * @param options Optional parameters such as condition expressions.\n */\n deleteItem(key: ItemKey, options?: DeleteItemOptions): Promise<void>;\n\n /**\n * Query items by primary key with optional range conditions. Returns an\n * {@link ItemListing} that handles pagination transparently, allowing the caller\n * to iterate over all matching items without managing page tokens.\n *\n * @param options Query parameters including key condition, range conditions,\n * filters, and pagination controls.\n * @returns An item listing that yields items and exposes a cursor for resuming.\n */\n query<T = Record<string, unknown>>(options: QueryOptions): ItemListing<T>;\n\n /**\n * Perform a full scan of the data store. Returns an {@link ItemListing} that\n * handles pagination transparently. Scans read every item in the table and\n * should be used sparingly.\n *\n * @param options Optional scan parameters such as filters and pagination controls.\n * @returns An item listing that yields items and exposes a cursor for resuming.\n */\n scan<T = Record<string, unknown>>(options?: ScanOptions): ItemListing<T>;\n\n /**\n * Retrieve multiple items by their primary keys in a single batch operation.\n * The batch may be split into multiple requests if it exceeds provider limits.\n *\n * @param keys The primary keys of the items to retrieve.\n * @param options Optional parameters such as consistent read.\n * @returns A promise that resolves to the batch get result, including retrieved\n * items and any unprocessed keys.\n */\n batchGetItems<T = Record<string, unknown>>(\n keys: ItemKey[],\n options?: BatchGetItemsOptions,\n ): Promise<BatchGetResult<T>>;\n\n /**\n * Perform multiple put and delete operations in a single batch. The batch may\n * be split into multiple requests if it exceeds provider limits.\n *\n * @param operations The batch of put and delete operations to execute.\n * @returns A promise that resolves to the batch write result, including any\n * unprocessed operations.\n */\n batchWriteItems(operations: BatchWriteOperation[]): Promise<BatchWriteResult>;\n}\n\n/**\n * Primary key attributes for an item. Keys can be string or number values\n * corresponding to primary key and optional range key attributes.\n */\nexport type ItemKey = Record<string, string | number>;\n\n/**\n * A condition on the primary key — always an equality match.\n */\nexport type KeyCondition = {\n /** The attribute name of the primary key. */\n name: string;\n /** The primary key value to match. */\n value: string | number;\n};\n\n/**\n * A condition on the range key. Supports equality, comparison, range,\n * and prefix matching operations.\n */\nexport type RangeCondition = {\n /** The attribute name of the range key. */\n name: string;\n} & (\n | { operator: \"eq\"; value: string | number }\n | { operator: \"lt\"; value: string | number }\n | { operator: \"le\"; value: string | number }\n | { operator: \"gt\"; value: string | number }\n | { operator: \"ge\"; value: string | number }\n | { operator: \"between\"; low: string | number; high: string | number }\n | { operator: \"startsWith\"; value: string }\n);\n\n/**\n * A filter condition on an item attribute. Used for post-read filtering\n * in queries and scans, and for conditional writes.\n *\n * Only includes operators that map cleanly across all target providers\n * (DynamoDB, Firestore, Cosmos DB). The `not_exists` operator is\n * provider-specific and available through the concrete provider classes.\n */\nexport type Condition = {\n /** The attribute name to evaluate. */\n name: string;\n} & (\n | { operator: \"eq\"; value: unknown }\n | { operator: \"ne\"; value: unknown }\n | { operator: \"lt\"; value: string | number }\n | { operator: \"le\"; value: string | number }\n | { operator: \"gt\"; value: string | number }\n | { operator: \"ge\"; value: string | number }\n | { operator: \"between\"; low: string | number; high: string | number }\n | { operator: \"startsWith\"; value: string }\n | { operator: \"contains\"; value: string | number }\n | { operator: \"exists\" }\n);\n\n/**\n * One or more conditions AND'd together. A single {@link Condition} or an array\n * of Conditions — when multiple are provided, all must be true.\n */\nexport type ConditionExpression = Condition | Condition[];\n\n/**\n * Options for the getItem operation.\n */\nexport type GetItemOptions = {\n /** When true, performs a strongly consistent read. Default is eventually consistent. */\n consistentRead?: boolean;\n};\n\n/**\n * Options for the putItem operation.\n */\nexport type PutItemOptions = {\n /**\n * Condition that must be met for the put to succeed. Throws\n * {@link ConditionalCheckFailedError} if the condition is not met.\n */\n condition?: ConditionExpression;\n};\n\n/**\n * Options for the deleteItem operation.\n */\nexport type DeleteItemOptions = {\n /**\n * Condition that must be met for the delete to succeed. Throws\n * {@link ConditionalCheckFailedError} if the condition is not met.\n */\n condition?: ConditionExpression;\n};\n\n/**\n * Options for the query operation.\n */\nexport type QueryOptions = {\n /** The primary key condition (required for queries). */\n key: KeyCondition;\n /** Optional range key condition to narrow the query range. */\n range?: RangeCondition;\n /** Optional filter conditions applied after the query read (does not reduce read capacity). */\n filter?: ConditionExpression;\n /** Query an index instead of the base table. */\n indexName?: string;\n /** When true, results are returned in ascending key order (default). Set to false for descending. */\n sortAscending?: boolean;\n /** Maximum number of items to return per internal page fetch. */\n maxResults?: number;\n /** Opaque cursor token to resume a previous query from where it left off. */\n cursor?: string;\n /** When true, performs a strongly consistent read (not supported on secondary indexes). */\n consistentRead?: boolean;\n};\n\n/**\n * Options for the scan operation.\n */\nexport type ScanOptions = {\n /** Optional filter conditions applied after the scan read. */\n filter?: ConditionExpression;\n /** Scan an index instead of the base table. */\n indexName?: string;\n /** Maximum number of items to return per internal page fetch. */\n maxResults?: number;\n /** Opaque cursor token to resume a previous scan from where it left off. */\n cursor?: string;\n /** When true, performs a strongly consistent read. */\n consistentRead?: boolean;\n};\n\n/**\n * An async iterable of items that also exposes a cursor token for resuming\n * iteration from the current position. The cursor is updated as pages are fetched\n * and encodes enough state to resume from the exact position across all providers.\n */\nexport interface ItemListing<T> extends AsyncIterable<T> {\n /**\n * A cursor token representing the current position in the listing. This token\n * can be passed to a subsequent query or scan call to resume iteration from\n * this position. The value is `undefined` before iteration begins or after all\n * items have been yielded.\n */\n readonly cursor: string | undefined;\n}\n\n/**\n * Options for the batchGetItems operation.\n */\nexport type BatchGetItemsOptions = {\n /** When true, performs strongly consistent reads for all items. */\n consistentRead?: boolean;\n};\n\n/**\n * The result of a batch get operation.\n */\nexport type BatchGetResult<T> = {\n /** The successfully retrieved items. */\n items: T[];\n /** Keys that could not be processed in this batch (caller should retry). */\n unprocessedKeys: ItemKey[];\n};\n\n/**\n * A single operation in a batch write request.\n */\nexport type BatchWriteOperation =\n | { type: \"put\"; item: Record<string, unknown> }\n | { type: \"delete\"; key: ItemKey };\n\n/**\n * The result of a batch write operation.\n */\nexport type BatchWriteResult = {\n /** Operations that could not be processed in this batch (caller should retry). */\n unprocessedOperations: BatchWriteOperation[];\n};\n","import { resolveConfig } from \"@celerity-sdk/config\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { DatastoreClient } from \"./types\";\nimport type { DynamoDBDatastoreConfig } from \"./providers/dynamodb/types\";\n\nexport type CreateDatastoreClientOptions = {\n /** Override provider selection. If omitted, derived from platform config. */\n provider?: \"aws\" | \"local\" | \"gcp\" | \"azure\";\n /** Cloud deploy target for local environments (e.g. \"aws\", \"gcloud\", \"azure\"). */\n deployTarget?: string;\n /** DynamoDB-specific configuration overrides. */\n aws?: DynamoDBDatastoreConfig;\n /** Optional tracer for Celerity-level span instrumentation. */\n tracer?: CelerityTracer;\n};\n\nexport async function createDatastoreClient(\n options?: CreateDatastoreClientOptions,\n): Promise<DatastoreClient> {\n const resolved = resolveConfig(\"datastore\");\n const provider = options?.provider ?? resolved.provider;\n\n switch (provider) {\n case \"aws\": {\n const { DynamoDBDatastoreClient } =\n await import(\"./providers/dynamodb/dynamodb-datastore-client.js\");\n return new DynamoDBDatastoreClient(options?.aws, options?.tracer);\n }\n case \"local\":\n return createLocalClient(options);\n default:\n throw new Error(`Unsupported datastore provider: \"${provider}\"`);\n }\n}\n\nasync function createLocalClient(options?: CreateDatastoreClientOptions): Promise<DatastoreClient> {\n const deployTarget = options?.deployTarget?.toLowerCase();\n\n switch (deployTarget) {\n case \"aws\":\n case \"aws-serverless\":\n case undefined: {\n // DynamoDB Local (v0 default when no deploy target is specified)\n const { captureDynamoDBConfig } = await import(\"./providers/dynamodb/config.js\");\n const { DynamoDBDatastoreClient } =\n await import(\"./providers/dynamodb/dynamodb-datastore-client.js\");\n const localConfig: DynamoDBDatastoreConfig = {\n ...captureDynamoDBConfig(),\n ...options?.aws,\n };\n return new DynamoDBDatastoreClient(localConfig, options?.tracer);\n }\n // case \"gcloud\":\n // case \"gcloud-serverless\":\n // v1: Firestore emulator\n // case \"azure\":\n // case \"azure-serverless\":\n // v1: Cosmos DB emulator\n default:\n throw new Error(\n `Unsupported local datastore deploy target: \"${deployTarget}\". Only AWS is supported in v0.`,\n );\n }\n}\n","import \"reflect-metadata\";\nimport { INJECT_METADATA, USE_RESOURCE_METADATA } from \"@celerity-sdk/common\";\nimport type { Datastore as DatastoreType } from \"./types\";\n\n// Re-declare as interface so the type merges with the decorator function below.\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface Datastore extends DatastoreType {}\n\nexport function datastoreToken(resourceName: string): symbol {\n return Symbol.for(`celerity:datastore:${resourceName}`);\n}\n\nexport const DEFAULT_DATASTORE_TOKEN = Symbol.for(\"celerity:datastore:default\");\n\n/**\n * Parameter decorator that injects a {@link Datastore} instance for the given\n * blueprint resource. Writes both DI injection metadata and CLI resource-ref\n * metadata using well-known `Symbol.for()` keys (no dependency on core).\n *\n * When `resourceName` is omitted, the default datastore token is used — this\n * auto-resolves when exactly one datastore resource exists.\n *\n * @example\n * ```ts\n * @Controller(\"/users\")\n * class UserController {\n * constructor(@Datastore(\"usersTable\") private users: Datastore) {}\n * }\n * ```\n */\nexport function Datastore(resourceName?: string): ParameterDecorator {\n return (target, _propertyKey, parameterIndex) => {\n const token = resourceName ? datastoreToken(resourceName) : DEFAULT_DATASTORE_TOKEN;\n const existing: Map<number, unknown> =\n Reflect.getOwnMetadata(INJECT_METADATA, target) ?? new Map();\n existing.set(parameterIndex, token);\n Reflect.defineMetadata(INJECT_METADATA, existing, target);\n\n if (resourceName) {\n const resources: string[] = Reflect.getOwnMetadata(USE_RESOURCE_METADATA, target) ?? [];\n if (!resources.includes(resourceName)) {\n Reflect.defineMetadata(USE_RESOURCE_METADATA, [...resources, resourceName], target);\n }\n }\n };\n}\n","import type { ServiceContainer } from \"@celerity-sdk/types\";\nimport type { Datastore } from \"./types\";\nimport { datastoreToken, DEFAULT_DATASTORE_TOKEN } from \"./decorators\";\n\n/**\n * Resolves a {@link Datastore} instance from the DI container.\n * For function-based handlers where parameter decorators aren't available.\n *\n * @param container - The service container (typically `context.container`).\n * @param resourceName - The blueprint resource name. Omit when exactly one\n * datastore resource exists to use the default.\n *\n * @example\n * ```ts\n * const handler = createHttpHandler(async (req, ctx) => {\n * const users = await getDatastore(ctx.container, \"usersTable\");\n * const user = await users.getItem({ pk: req.pathParameters.userId });\n * });\n * ```\n */\nexport function getDatastore(\n container: ServiceContainer,\n resourceName?: string,\n): Promise<Datastore> {\n const token = resourceName ? datastoreToken(resourceName) : DEFAULT_DATASTORE_TOKEN;\n return container.resolve<Datastore>(token);\n}\n","import createDebug from \"debug\";\nimport type { CelerityLayer, BaseHandlerContext, CelerityTracer } from \"@celerity-sdk/types\";\nimport { TRACER_TOKEN, CONFIG_SERVICE_TOKEN } from \"@celerity-sdk/common\";\nimport {\n type ConfigService,\n captureResourceLinks,\n getLinksOfType,\n RESOURCE_CONFIG_NAMESPACE,\n} from \"@celerity-sdk/config\";\nimport { createDatastoreClient } from \"./factory\";\nimport { datastoreToken, DEFAULT_DATASTORE_TOKEN } from \"./decorators\";\n\nconst debug = createDebug(\"celerity:datastore\");\n\n/**\n * System layer that auto-registers {@link DatastoreClient} and per-resource\n * {@link Datastore} handles in the DI container.\n *\n * Reads resource link topology from `CELERITY_RESOURCE_LINKS` and resolves\n * actual table/collection names from the ConfigService \"resources\" namespace.\n * Must run after ConfigLayer in the layer pipeline.\n */\ntype DatastoreLayerConfig = {\n deployTarget: string | undefined;\n};\n\nfunction captureDatastoreLayerConfig(): DatastoreLayerConfig {\n return {\n deployTarget: process.env.CELERITY_DEPLOY_TARGET,\n };\n}\n\nexport class DatastoreLayer implements CelerityLayer<BaseHandlerContext> {\n private initialized = false;\n private config: DatastoreLayerConfig | null = null;\n\n async handle(context: BaseHandlerContext, next: () => Promise<unknown>): Promise<unknown> {\n if (!this.initialized) {\n this.config = captureDatastoreLayerConfig();\n\n const tracer = context.container.has(TRACER_TOKEN)\n ? await context.container.resolve<CelerityTracer>(TRACER_TOKEN)\n : undefined;\n\n const client = await createDatastoreClient({\n tracer,\n deployTarget: this.config.deployTarget,\n });\n debug(\"registering DatastoreClient\");\n context.container.register(\"DatastoreClient\", { useValue: client });\n\n const links = captureResourceLinks();\n const datastoreLinks = getLinksOfType(links, \"datastore\");\n\n if (datastoreLinks.size > 0) {\n const configService = await context.container.resolve<ConfigService>(CONFIG_SERVICE_TOKEN);\n const resourceConfig = configService.namespace(RESOURCE_CONFIG_NAMESPACE);\n\n for (const [resourceName, configKey] of datastoreLinks) {\n const actualName = await resourceConfig.getOrThrow(configKey);\n debug(\"registered datastore resource %s → %s\", resourceName, actualName);\n context.container.register(datastoreToken(resourceName), {\n useValue: client.datastore(actualName),\n });\n }\n\n if (datastoreLinks.size === 1) {\n const [, configKey] = [...datastoreLinks.entries()][0];\n const actualName = await resourceConfig.getOrThrow(configKey);\n debug(\"registered default datastore → %s\", actualName);\n context.container.register(DEFAULT_DATASTORE_TOKEN, {\n useValue: client.datastore(actualName),\n });\n }\n }\n\n this.initialized = true;\n }\n\n return next();\n }\n}\n"],"mappings":"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","names":["DatastoreError","ConditionalCheckFailedError","Error","message","table","options","name","buildKeyConditionExpression","key","range","names","values","counter","pkName","pkValue","name","value","expression","skName","operator","skValue","COMPARISON_OPERATORS","lowVal","highVal","low","high","buildFilterExpression","conditions","condArray","Array","isArray","parts","cond","attrName","valKey","push","fnName","join","eq","ne","lt","le","gt","ge","encodeCursor","lastEvaluatedKey","state","Buffer","from","JSON","stringify","toString","decodeCursor","cursor","parse","debug","DynamoDBItemListing","createDebug","_cursor","client","tableName","mode","options","tracer","Symbol","asyncIterator","cursorState","undefined","exclusiveStartKey","response","fetchPage","item","Items","LastEvaluatedKey","command","buildQueryCommand","buildScanCommand","doFetch","send","error","DatastoreError","cause","withSpan","opts","keyExpr","buildKeyConditionExpression","key","range","filterExpr","filter","buildFilterExpression","QueryCommand","TableName","IndexName","indexName","KeyConditionExpression","expression","FilterExpression","ExpressionAttributeNames","names","ExpressionAttributeValues","values","ScanIndexForward","sortAscending","Limit","maxResults","ExclusiveStartKey","ConsistentRead","consistentRead","ScanCommand","Object","keys","length","isConditionalCheckFailedError","error","Error","name","init_errors","import_debug","import_lib_dynamodb","debug","DynamoDBDatastore","init_errors","createDebug","tableName","client","tracer","getItem","key","options","traced","response","send","GetCommand","TableName","Key","ConsistentRead","consistentRead","Item","error","DatastoreError","cause","putItem","item","conditionParams","condition","buildFilterExpression","undefined","PutCommand","ConditionExpression","expression","ExpressionAttributeNames","names","ExpressionAttributeValues","values","isConditionalCheckFailedError","ConditionalCheckFailedError","deleteItem","DeleteCommand","query","name","DynamoDBItemListing","scan","batchGetItems","keys","length","BatchGetCommand","RequestItems","Keys","items","Responses","unprocessedKeys","UnprocessedKeys","batchWriteItems","operations","writeRequests","map","op","type","PutRequest","DeleteRequest","BatchWriteCommand","unprocessedRequests","UnprocessedItems","unprocessedOperations","req","attributes","fn","withSpan","span","captureDynamoDBConfig","region","process","env","AWS_REGION","AWS_DEFAULT_REGION","endpoint","CELERITY_AWS_DYNAMODB_ENDPOINT","AWS_ENDPOINT_URL","credentials","AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","accessKeyId","secretAccessKey","undefined","import_lib_dynamodb","DynamoDBDatastoreClient","client","docClient","config","tracer","captureDynamoDBConfig","datastore","name","DynamoDBDatastore","getDocClient","close","destroy","DynamoDBClient","region","endpoint","credentials","DynamoDBDocumentClient","from","marshallOptions","removeUndefinedValues","DatastoreClient","Symbol","for","import_config","createDatastoreClient","options","resolved","resolveConfig","provider","DynamoDBDatastoreClient","aws","tracer","createLocalClient","Error","deployTarget","toLowerCase","undefined","captureDynamoDBConfig","localConfig","datastoreToken","resourceName","Symbol","for","DEFAULT_DATASTORE_TOKEN","Datastore","target","_propertyKey","parameterIndex","token","existing","Reflect","getOwnMetadata","INJECT_METADATA","Map","set","defineMetadata","resources","USE_RESOURCE_METADATA","includes","getDatastore","container","resourceName","token","datastoreToken","DEFAULT_DATASTORE_TOKEN","resolve","import_debug","import_common","import_config","debug","createDebug","captureDatastoreLayerConfig","deployTarget","process","env","CELERITY_DEPLOY_TARGET","DatastoreLayer","initialized","config","handle","context","next","tracer","container","has","TRACER_TOKEN","resolve","undefined","client","createDatastoreClient","register","useValue","links","captureResourceLinks","datastoreLinks","getLinksOfType","size","configService","CONFIG_SERVICE_TOKEN","resourceConfig","namespace","RESOURCE_CONFIG_NAMESPACE","resourceName","configKey","actualName","getOrThrow","datastoreToken","datastore","entries","DEFAULT_DATASTORE_TOKEN"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/providers/dynamodb/expressions.ts","../src/providers/dynamodb/dynamodb-item-listing.ts","../src/providers/dynamodb/errors.ts","../src/providers/dynamodb/dynamodb-datastore.ts","../src/providers/dynamodb/config.ts","../src/providers/dynamodb/dynamodb-datastore-client.ts","../src/index.ts","../src/types.ts","../src/factory.ts","../src/decorators.ts","../src/helpers.ts","../src/layer.ts"],"sourcesContent":["export class DatastoreError extends Error {\n constructor(\n message: string,\n public readonly table: string,\n options?: { cause?: unknown },\n ) {\n super(message, options);\n this.name = \"DatastoreError\";\n }\n}\n\nexport class ConditionalCheckFailedError extends DatastoreError {\n constructor(table: string, options?: { cause?: unknown }) {\n super(`Conditional check failed on table \"${table}\"`, table, options);\n this.name = \"ConditionalCheckFailedError\";\n }\n}\n","import type {\n Condition,\n KeyCondition,\n RangeCondition,\n ConditionExpression,\n AndGroup,\n OrGroup,\n} from \"../../types\";\n\nexport type ExpressionResult = {\n expression: string;\n names: Record<string, string>;\n values: Record<string, unknown>;\n};\n\nconst COMPARISON_OPERATORS = {\n eq: \"=\",\n ne: \"<>\",\n lt: \"<\",\n le: \"<=\",\n gt: \">\",\n ge: \">=\",\n} as const;\n\n/**\n * Builds a DynamoDB KeyConditionExpression from a key condition and optional range condition.\n * Uses `#k`/`:k` prefixed placeholders to avoid collision with filter placeholders.\n */\nexport function buildKeyConditionExpression(\n key: KeyCondition,\n range?: RangeCondition,\n): ExpressionResult {\n const names: Record<string, string> = {};\n const values: Record<string, unknown> = {};\n let counter = 0;\n\n const pkName = `#k${counter}`;\n const pkValue = `:k${counter}`;\n names[pkName] = key.name;\n values[pkValue] = key.value;\n counter++;\n\n let expression = `${pkName} = ${pkValue}`;\n\n if (range) {\n const skName = `#k${counter}`;\n names[skName] = range.name;\n\n switch (range.operator) {\n case \"eq\":\n case \"lt\":\n case \"le\":\n case \"gt\":\n case \"ge\": {\n const skValue = `:k${counter}`;\n values[skValue] = range.value;\n expression += ` AND ${skName} ${COMPARISON_OPERATORS[range.operator]} ${skValue}`;\n break;\n }\n case \"between\": {\n const lowVal = `:k${counter}a`;\n const highVal = `:k${counter}b`;\n values[lowVal] = range.low;\n values[highVal] = range.high;\n expression += ` AND ${skName} BETWEEN ${lowVal} AND ${highVal}`;\n break;\n }\n case \"startsWith\": {\n const skValue = `:k${counter}`;\n values[skValue] = range.value;\n expression += ` AND begins_with(${skName}, ${skValue})`;\n break;\n }\n }\n }\n\n return { expression, names, values };\n}\n\ntype MutableCounter = { value: number };\n\n/**\n * Builds a DynamoDB FilterExpression (or ConditionExpression for writes)\n * from a condition expression tree. Supports single conditions, arrays of\n * conditions (implicit AND), and explicit AND/OR groups with recursive nesting.\n * Uses `#f`/`:f` prefixed placeholders to avoid collision with key placeholders.\n */\nexport function buildFilterExpression(conditions: ConditionExpression): ExpressionResult {\n const names: Record<string, string> = {};\n const values: Record<string, unknown> = {};\n const counter: MutableCounter = { value: 0 };\n\n const expression = buildExpressionNode(conditions, names, values, counter, 0);\n return { expression, names, values };\n}\n\nfunction buildExpressionNode(\n expr: ConditionExpression,\n names: Record<string, string>,\n values: Record<string, unknown>,\n counter: MutableCounter,\n depth: number,\n): string {\n if (Array.isArray(expr)) {\n return buildGroup(expr, \"AND\", names, values, counter, depth);\n }\n if (isOrGroup(expr)) {\n return buildGroup(expr.or, \"OR\", names, values, counter, depth);\n }\n if (isAndGroup(expr)) {\n return buildGroup(expr.and, \"AND\", names, values, counter, depth);\n }\n return buildSingleCondition(expr, names, values, counter);\n}\n\nfunction buildGroup(\n children: ConditionExpression[],\n operator: \"AND\" | \"OR\",\n names: Record<string, string>,\n values: Record<string, unknown>,\n counter: MutableCounter,\n depth: number,\n): string {\n const parts = children.map((child) =>\n buildExpressionNode(child, names, values, counter, depth + 1),\n );\n\n if (parts.length === 1) return parts[0];\n\n const joined = parts.join(` ${operator} `);\n return depth > 0 ? `(${joined})` : joined;\n}\n\nfunction buildSingleCondition(\n cond: Condition,\n names: Record<string, string>,\n values: Record<string, unknown>,\n counter: MutableCounter,\n): string {\n const i = counter.value;\n const attrName = `#f${i}`;\n names[attrName] = cond.name;\n counter.value++;\n\n switch (cond.operator) {\n case \"eq\":\n case \"ne\":\n case \"lt\":\n case \"le\":\n case \"gt\":\n case \"ge\": {\n const valKey = `:f${i}`;\n values[valKey] = cond.value;\n return `${attrName} ${COMPARISON_OPERATORS[cond.operator]} ${valKey}`;\n }\n case \"between\": {\n const lowVal = `:f${i}a`;\n const highVal = `:f${i}b`;\n values[lowVal] = cond.low;\n values[highVal] = cond.high;\n return `${attrName} BETWEEN ${lowVal} AND ${highVal}`;\n }\n case \"startsWith\":\n case \"contains\": {\n const valKey = `:f${i}`;\n values[valKey] = cond.value;\n const fnName = cond.operator === \"startsWith\" ? \"begins_with\" : \"contains\";\n return `${fnName}(${attrName}, ${valKey})`;\n }\n case \"exists\":\n return `attribute_exists(${attrName})`;\n }\n}\n\nfunction isAndGroup(expr: ConditionExpression): expr is AndGroup {\n return typeof expr === \"object\" && !Array.isArray(expr) && \"and\" in expr;\n}\n\nfunction isOrGroup(expr: ConditionExpression): expr is OrGroup {\n return typeof expr === \"object\" && !Array.isArray(expr) && \"or\" in expr;\n}\n","import createDebug from \"debug\";\nimport { QueryCommand, ScanCommand, type DynamoDBDocumentClient } from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { ItemListing, QueryOptions, ScanOptions } from \"../../types\";\nimport { DatastoreError } from \"../../errors\";\nimport { buildKeyConditionExpression, buildFilterExpression } from \"./expressions\";\n\nconst debug = createDebug(\"celerity:datastore:dynamodb\");\n\ntype CursorState = {\n lastEvaluatedKey: Record<string, unknown>;\n};\n\nfunction encodeCursor(lastEvaluatedKey: Record<string, unknown>): string {\n const state: CursorState = { lastEvaluatedKey };\n return Buffer.from(JSON.stringify(state)).toString(\"base64url\");\n}\n\nfunction decodeCursor(cursor: string): CursorState {\n return JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\")) as CursorState;\n}\n\nexport class DynamoDBItemListing<T> implements ItemListing<T> {\n private _cursor: string | undefined;\n\n constructor(\n private readonly client: DynamoDBDocumentClient,\n private readonly tableName: string,\n private readonly mode: \"query\" | \"scan\",\n private readonly options: QueryOptions | ScanOptions,\n private readonly tracer?: CelerityTracer,\n ) {\n this._cursor = options.cursor;\n }\n\n get cursor(): string | undefined {\n return this._cursor;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n const cursorState = this._cursor ? decodeCursor(this._cursor) : undefined;\n let exclusiveStartKey: Record<string, unknown> | undefined = cursorState?.lastEvaluatedKey;\n\n do {\n debug(\"%s page %s key=%o\", this.mode, this.tableName, exclusiveStartKey ?? \"(start)\");\n\n const response = await this.fetchPage(exclusiveStartKey);\n\n for (const item of response.Items ?? []) {\n yield item as T;\n }\n\n exclusiveStartKey = response.LastEvaluatedKey as Record<string, unknown> | undefined;\n\n if (exclusiveStartKey) {\n this._cursor = encodeCursor(exclusiveStartKey);\n } else {\n this._cursor = undefined;\n }\n } while (exclusiveStartKey);\n }\n\n private async fetchPage(exclusiveStartKey?: Record<string, unknown>) {\n const command =\n this.mode === \"query\"\n ? this.buildQueryCommand(exclusiveStartKey)\n : this.buildScanCommand(exclusiveStartKey);\n\n const doFetch = async () => {\n try {\n return await this.client.send(command);\n } catch (error) {\n throw new DatastoreError(\n `Failed to ${this.mode} table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n };\n\n if (!this.tracer) return doFetch();\n return this.tracer.withSpan(`celerity.datastore.${this.mode}_page`, () => doFetch(), {\n \"datastore.table\": this.tableName,\n });\n }\n\n private buildQueryCommand(exclusiveStartKey?: Record<string, unknown>) {\n const opts = this.options as QueryOptions;\n const keyExpr = buildKeyConditionExpression(opts.key, opts.range);\n\n const filterExpr = opts.filter ? buildFilterExpression(opts.filter) : undefined;\n\n return new QueryCommand({\n TableName: this.tableName,\n IndexName: opts.indexName,\n KeyConditionExpression: keyExpr.expression,\n FilterExpression: filterExpr?.expression,\n ExpressionAttributeNames: { ...keyExpr.names, ...filterExpr?.names },\n ExpressionAttributeValues: { ...keyExpr.values, ...filterExpr?.values },\n ScanIndexForward: opts.sortAscending,\n Limit: opts.maxResults,\n ExclusiveStartKey: exclusiveStartKey,\n ConsistentRead: opts.consistentRead,\n });\n }\n\n private buildScanCommand(exclusiveStartKey?: Record<string, unknown>) {\n const opts = this.options as ScanOptions;\n\n const filterExpr = opts.filter ? buildFilterExpression(opts.filter) : undefined;\n\n return new ScanCommand({\n TableName: this.tableName,\n IndexName: opts.indexName,\n FilterExpression: filterExpr?.expression,\n ExpressionAttributeNames:\n filterExpr?.names && Object.keys(filterExpr.names).length > 0\n ? filterExpr.names\n : undefined,\n ExpressionAttributeValues:\n filterExpr?.values && Object.keys(filterExpr.values).length > 0\n ? filterExpr.values\n : undefined,\n Limit: opts.maxResults,\n ExclusiveStartKey: exclusiveStartKey,\n ConsistentRead: opts.consistentRead,\n });\n }\n}\n","/**\n * Checks if an error is a DynamoDB ConditionalCheckFailedException.\n */\nexport function isConditionalCheckFailedError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n return (error as { name?: string }).name === \"ConditionalCheckFailedException\";\n}\n","import createDebug from \"debug\";\nimport {\n GetCommand,\n PutCommand,\n DeleteCommand,\n BatchGetCommand,\n BatchWriteCommand,\n type DynamoDBDocumentClient,\n} from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer, CeleritySpan } from \"@celerity-sdk/types\";\nimport type {\n Datastore,\n ItemKey,\n GetItemOptions,\n PutItemOptions,\n DeleteItemOptions,\n QueryOptions,\n ScanOptions,\n ItemListing,\n BatchGetItemsOptions,\n BatchGetResult,\n BatchWriteOperation,\n BatchWriteResult,\n} from \"../../types\";\nimport { DatastoreError, ConditionalCheckFailedError } from \"../../errors\";\nimport { DynamoDBItemListing } from \"./dynamodb-item-listing\";\nimport { buildFilterExpression } from \"./expressions\";\nimport { isConditionalCheckFailedError } from \"./errors\";\n\nconst debug = createDebug(\"celerity:datastore:dynamodb\");\n\nexport class DynamoDBDatastore implements Datastore {\n constructor(\n private readonly tableName: string,\n private readonly client: DynamoDBDocumentClient,\n private readonly tracer?: CelerityTracer,\n ) {}\n\n async getItem<T = Record<string, unknown>>(\n key: ItemKey,\n options?: GetItemOptions,\n ): Promise<T | null> {\n debug(\"getItem %s %o\", this.tableName, key);\n return this.traced(\n \"celerity.datastore.get_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const response = await this.client.send(\n new GetCommand({\n TableName: this.tableName,\n Key: key,\n ConsistentRead: options?.consistentRead,\n }),\n );\n return (response.Item as T) ?? null;\n } catch (error) {\n throw new DatastoreError(\n `Failed to get item from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async putItem(item: Record<string, unknown>, options?: PutItemOptions): Promise<void> {\n debug(\"putItem %s\", this.tableName);\n return this.traced(\n \"celerity.datastore.put_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const conditionParams = options?.condition\n ? buildFilterExpression(options.condition)\n : undefined;\n\n await this.client.send(\n new PutCommand({\n TableName: this.tableName,\n Item: item,\n ConditionExpression: conditionParams?.expression,\n ExpressionAttributeNames: conditionParams?.names,\n ExpressionAttributeValues: conditionParams?.values,\n }),\n );\n } catch (error) {\n if (isConditionalCheckFailedError(error)) {\n throw new ConditionalCheckFailedError(this.tableName, { cause: error });\n }\n throw new DatastoreError(\n `Failed to put item in table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async deleteItem(key: ItemKey, options?: DeleteItemOptions): Promise<void> {\n debug(\"deleteItem %s %o\", this.tableName, key);\n return this.traced(\n \"celerity.datastore.delete_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const conditionParams = options?.condition\n ? buildFilterExpression(options.condition)\n : undefined;\n\n await this.client.send(\n new DeleteCommand({\n TableName: this.tableName,\n Key: key,\n ConditionExpression: conditionParams?.expression,\n ExpressionAttributeNames: conditionParams?.names,\n ExpressionAttributeValues: conditionParams?.values,\n }),\n );\n } catch (error) {\n if (isConditionalCheckFailedError(error)) {\n throw new ConditionalCheckFailedError(this.tableName, { cause: error });\n }\n throw new DatastoreError(\n `Failed to delete item from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n query<T = Record<string, unknown>>(options: QueryOptions): ItemListing<T> {\n debug(\"query %s pk=%s\", this.tableName, options.key.name);\n return new DynamoDBItemListing<T>(this.client, this.tableName, \"query\", options, this.tracer);\n }\n\n scan<T = Record<string, unknown>>(options?: ScanOptions): ItemListing<T> {\n debug(\"scan %s\", this.tableName);\n return new DynamoDBItemListing<T>(\n this.client,\n this.tableName,\n \"scan\",\n options ?? {},\n this.tracer,\n );\n }\n\n async batchGetItems<T = Record<string, unknown>>(\n keys: ItemKey[],\n options?: BatchGetItemsOptions,\n ): Promise<BatchGetResult<T>> {\n debug(\"batchGetItems %s count=%d\", this.tableName, keys.length);\n return this.traced(\n \"celerity.datastore.batch_get_items\",\n { \"datastore.table\": this.tableName, \"datastore.batch_size\": keys.length },\n async () => {\n try {\n const response = await this.client.send(\n new BatchGetCommand({\n RequestItems: {\n [this.tableName]: {\n Keys: keys,\n ConsistentRead: options?.consistentRead,\n },\n },\n }),\n );\n\n const items = (response.Responses?.[this.tableName] ?? []) as T[];\n const unprocessedKeys = (response.UnprocessedKeys?.[this.tableName]?.Keys ??\n []) as ItemKey[];\n\n return { items, unprocessedKeys };\n } catch (error) {\n throw new DatastoreError(\n `Failed to batch get items from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async batchWriteItems(operations: BatchWriteOperation[]): Promise<BatchWriteResult> {\n debug(\"batchWriteItems %s count=%d\", this.tableName, operations.length);\n return this.traced(\n \"celerity.datastore.batch_write_items\",\n { \"datastore.table\": this.tableName, \"datastore.batch_size\": operations.length },\n async () => {\n try {\n const writeRequests = operations.map((op) => {\n if (op.type === \"put\") {\n return { PutRequest: { Item: op.item } };\n }\n return { DeleteRequest: { Key: op.key } };\n });\n\n const response = await this.client.send(\n new BatchWriteCommand({\n RequestItems: { [this.tableName]: writeRequests },\n }),\n );\n\n const unprocessedRequests = response.UnprocessedItems?.[this.tableName] ?? [];\n const unprocessedOperations: BatchWriteOperation[] = unprocessedRequests.map((req) => {\n if (req.PutRequest) {\n return { type: \"put\" as const, item: req.PutRequest.Item! };\n }\n return { type: \"delete\" as const, key: req.DeleteRequest!.Key! as ItemKey };\n });\n\n return { unprocessedOperations };\n } catch (error) {\n throw new DatastoreError(\n `Failed to batch write items to table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n private traced<T>(\n name: string,\n attributes: Record<string, string | number | boolean>,\n fn: (span?: CeleritySpan) => Promise<T>,\n ): Promise<T> {\n if (!this.tracer) return fn();\n return this.tracer.withSpan(name, (span) => fn(span), attributes);\n }\n}\n","import type { DynamoDBDatastoreConfig } from \"./types\";\n\n/**\n * Captures DynamoDB configuration from environment variables.\n * This is the only place that reads `process.env` for DynamoDB config.\n */\nexport function captureDynamoDBConfig(): DynamoDBDatastoreConfig {\n return {\n region: process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION,\n endpoint: process.env.CELERITY_AWS_DYNAMODB_ENDPOINT ?? process.env.AWS_ENDPOINT_URL,\n credentials:\n process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY\n ? {\n accessKeyId: process.env.AWS_ACCESS_KEY_ID,\n secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\n }\n : undefined,\n };\n}\n","import { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";\nimport { DynamoDBDocumentClient } from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { DatastoreClient, Datastore } from \"../../types\";\nimport { DynamoDBDatastore } from \"./dynamodb-datastore\";\nimport type { DynamoDBDatastoreConfig } from \"./types\";\nimport { captureDynamoDBConfig } from \"./config\";\n\nexport class DynamoDBDatastoreClient implements DatastoreClient {\n private client: DynamoDBClient | null = null;\n private docClient: DynamoDBDocumentClient | null = null;\n private readonly config: DynamoDBDatastoreConfig;\n\n constructor(\n config?: DynamoDBDatastoreConfig,\n private readonly tracer?: CelerityTracer,\n ) {\n this.config = config ?? captureDynamoDBConfig();\n }\n\n datastore(name: string): Datastore {\n return new DynamoDBDatastore(name, this.getDocClient(), this.tracer);\n }\n\n close(): void {\n this.docClient?.destroy();\n this.client?.destroy();\n this.docClient = null;\n this.client = null;\n }\n\n private getDocClient(): DynamoDBDocumentClient {\n if (!this.docClient) {\n this.client = new DynamoDBClient({\n region: this.config.region,\n endpoint: this.config.endpoint,\n credentials: this.config.credentials,\n });\n this.docClient = DynamoDBDocumentClient.from(this.client, {\n marshallOptions: { removeUndefinedValues: true },\n });\n }\n return this.docClient;\n }\n}\n","export {\n DatastoreClient,\n type ItemKey,\n type KeyCondition,\n type RangeCondition,\n type Condition,\n type AndGroup,\n type OrGroup,\n type ConditionExpression,\n type GetItemOptions,\n type PutItemOptions,\n type DeleteItemOptions,\n type QueryOptions,\n type ScanOptions,\n type ItemListing,\n type BatchGetItemsOptions,\n type BatchGetResult,\n type BatchWriteOperation,\n type BatchWriteResult,\n} from \"./types\";\n\nexport type { DynamoDBDatastoreConfig } from \"./providers/dynamodb/types\";\n\nexport { createDatastoreClient } from \"./factory\";\nexport type { CreateDatastoreClientOptions } from \"./factory\";\n\nexport { Datastore, datastoreToken, DEFAULT_DATASTORE_TOKEN } from \"./decorators\";\nexport { getDatastore } from \"./helpers\";\nexport { DatastoreLayer } from \"./layer\";\nexport { DatastoreError, ConditionalCheckFailedError } from \"./errors\";\n","import type { Closeable } from \"@celerity-sdk/types\";\n\nexport const DatastoreClient = Symbol.for(\"DatastoreClient\");\n\n/**\n * A data store client abstraction for NoSQL databases. Provides access to named\n * data stores (tables/collections), each representing a logical container for items.\n */\nexport interface DatastoreClient extends Closeable {\n /**\n * Retrieves a datastore instance by its logical name. The returned datastore\n * is a lightweight handle — no network calls are made until an operation is invoked.\n *\n * @param name The name of the datastore (table/collection).\n */\n datastore(name: string): Datastore;\n}\n\n/**\n * A datastore represents a logical container (table/collection) for items in a\n * NoSQL data store. It provides methods for performing CRUD operations, queries,\n * scans, and batch operations within the data store.\n */\nexport interface Datastore {\n /**\n * Retrieve an item from the data store by its primary key. Returns `null` if the\n * item does not exist.\n *\n * @param key The primary key attributes identifying the item.\n * @param options Optional parameters such as consistent read.\n * @returns A promise that resolves to the item, or `null` if not found.\n */\n getItem<T = Record<string, unknown>>(key: ItemKey, options?: GetItemOptions): Promise<T | null>;\n\n /**\n * Store an item in the data store. If an item with the same primary key already\n * exists, it is replaced entirely (upsert semantics).\n *\n * @param item The item to store. Must include all primary key attributes.\n * @param options Optional parameters such as condition expressions.\n */\n putItem(item: Record<string, unknown>, options?: PutItemOptions): Promise<void>;\n\n /**\n * Delete an item from the data store by its primary key. This operation is\n * idempotent — deleting a non-existent key does not throw.\n *\n * @param key The primary key attributes identifying the item to delete.\n * @param options Optional parameters such as condition expressions.\n */\n deleteItem(key: ItemKey, options?: DeleteItemOptions): Promise<void>;\n\n /**\n * Query items by primary key with optional range conditions. Returns an\n * {@link ItemListing} that handles pagination transparently, allowing the caller\n * to iterate over all matching items without managing page tokens.\n *\n * @param options Query parameters including key condition, range conditions,\n * filters, and pagination controls.\n * @returns An item listing that yields items and exposes a cursor for resuming.\n */\n query<T = Record<string, unknown>>(options: QueryOptions): ItemListing<T>;\n\n /**\n * Perform a full scan of the data store. Returns an {@link ItemListing} that\n * handles pagination transparently. Scans read every item in the table and\n * should be used sparingly.\n *\n * @param options Optional scan parameters such as filters and pagination controls.\n * @returns An item listing that yields items and exposes a cursor for resuming.\n */\n scan<T = Record<string, unknown>>(options?: ScanOptions): ItemListing<T>;\n\n /**\n * Retrieve multiple items by their primary keys in a single batch operation.\n * The batch may be split into multiple requests if it exceeds provider limits.\n *\n * @param keys The primary keys of the items to retrieve.\n * @param options Optional parameters such as consistent read.\n * @returns A promise that resolves to the batch get result, including retrieved\n * items and any unprocessed keys.\n */\n batchGetItems<T = Record<string, unknown>>(\n keys: ItemKey[],\n options?: BatchGetItemsOptions,\n ): Promise<BatchGetResult<T>>;\n\n /**\n * Perform multiple put and delete operations in a single batch. The batch may\n * be split into multiple requests if it exceeds provider limits.\n *\n * @param operations The batch of put and delete operations to execute.\n * @returns A promise that resolves to the batch write result, including any\n * unprocessed operations.\n */\n batchWriteItems(operations: BatchWriteOperation[]): Promise<BatchWriteResult>;\n}\n\n/**\n * Primary key attributes for an item. Keys can be string or number values\n * corresponding to primary key and optional range key attributes.\n */\nexport type ItemKey = Record<string, string | number>;\n\n/**\n * A condition on the primary key — always an equality match.\n */\nexport type KeyCondition = {\n /** The attribute name of the primary key. */\n name: string;\n /** The primary key value to match. */\n value: string | number;\n};\n\n/**\n * A condition on the range key. Supports equality, comparison, range,\n * and prefix matching operations.\n */\nexport type RangeCondition = {\n /** The attribute name of the range key. */\n name: string;\n} & (\n | { operator: \"eq\"; value: string | number }\n | { operator: \"lt\"; value: string | number }\n | { operator: \"le\"; value: string | number }\n | { operator: \"gt\"; value: string | number }\n | { operator: \"ge\"; value: string | number }\n | { operator: \"between\"; low: string | number; high: string | number }\n | { operator: \"startsWith\"; value: string }\n);\n\n/**\n * A filter condition on an item attribute. Used for post-read filtering\n * in queries and scans, and for conditional writes.\n *\n * Only includes operators that map cleanly across all target providers\n * (DynamoDB, Firestore, Cosmos DB). The `not_exists` operator is\n * provider-specific and available through the concrete provider classes.\n */\nexport type Condition = {\n /** The attribute name to evaluate. */\n name: string;\n} & (\n | { operator: \"eq\"; value: unknown }\n | { operator: \"ne\"; value: unknown }\n | { operator: \"lt\"; value: string | number }\n | { operator: \"le\"; value: string | number }\n | { operator: \"gt\"; value: string | number }\n | { operator: \"ge\"; value: string | number }\n | { operator: \"between\"; low: string | number; high: string | number }\n | { operator: \"startsWith\"; value: string }\n | { operator: \"contains\"; value: string | number }\n | { operator: \"exists\" }\n);\n\n/**\n * A group of conditions combined with AND logic. All conditions must be true.\n */\nexport type AndGroup = { and: ConditionExpression[] };\n\n/**\n * A group of conditions combined with OR logic. At least one condition must be true.\n */\nexport type OrGroup = { or: ConditionExpression[] };\n\n/**\n * One or more conditions combined with logical operators. A single {@link Condition},\n * an array of Conditions (implicit AND), or explicit\n * {@link AndGroup}/{@link OrGroup} for compound logic with recursive nesting.\n */\nexport type ConditionExpression = Condition | Condition[] | AndGroup | OrGroup;\n\n/**\n * Options for the getItem operation.\n */\nexport type GetItemOptions = {\n /** When true, performs a strongly consistent read. Default is eventually consistent. */\n consistentRead?: boolean;\n};\n\n/**\n * Options for the putItem operation.\n */\nexport type PutItemOptions = {\n /**\n * Condition that must be met for the put to succeed. Throws\n * {@link ConditionalCheckFailedError} if the condition is not met.\n */\n condition?: ConditionExpression;\n};\n\n/**\n * Options for the deleteItem operation.\n */\nexport type DeleteItemOptions = {\n /**\n * Condition that must be met for the delete to succeed. Throws\n * {@link ConditionalCheckFailedError} if the condition is not met.\n */\n condition?: ConditionExpression;\n};\n\n/**\n * Options for the query operation.\n */\nexport type QueryOptions = {\n /** The primary key condition (required for queries). */\n key: KeyCondition;\n /** Optional range key condition to narrow the query range. */\n range?: RangeCondition;\n /** Optional filter conditions applied after the query read (does not reduce read capacity). */\n filter?: ConditionExpression;\n /** Query an index instead of the base table. */\n indexName?: string;\n /** When true, results are returned in ascending key order (default). Set to false for descending. */\n sortAscending?: boolean;\n /** Maximum number of items to return per internal page fetch. */\n maxResults?: number;\n /** Opaque cursor token to resume a previous query from where it left off. */\n cursor?: string;\n /** When true, performs a strongly consistent read (not supported on secondary indexes). */\n consistentRead?: boolean;\n};\n\n/**\n * Options for the scan operation.\n */\nexport type ScanOptions = {\n /** Optional filter conditions applied after the scan read. */\n filter?: ConditionExpression;\n /** Scan an index instead of the base table. */\n indexName?: string;\n /** Maximum number of items to return per internal page fetch. */\n maxResults?: number;\n /** Opaque cursor token to resume a previous scan from where it left off. */\n cursor?: string;\n /** When true, performs a strongly consistent read. */\n consistentRead?: boolean;\n};\n\n/**\n * An async iterable of items that also exposes a cursor token for resuming\n * iteration from the current position. The cursor is updated as pages are fetched\n * and encodes enough state to resume from the exact position across all providers.\n */\nexport interface ItemListing<T> extends AsyncIterable<T> {\n /**\n * A cursor token representing the current position in the listing. This token\n * can be passed to a subsequent query or scan call to resume iteration from\n * this position. The value is `undefined` before iteration begins or after all\n * items have been yielded.\n */\n readonly cursor: string | undefined;\n}\n\n/**\n * Options for the batchGetItems operation.\n */\nexport type BatchGetItemsOptions = {\n /** When true, performs strongly consistent reads for all items. */\n consistentRead?: boolean;\n};\n\n/**\n * The result of a batch get operation.\n */\nexport type BatchGetResult<T> = {\n /** The successfully retrieved items. */\n items: T[];\n /** Keys that could not be processed in this batch (caller should retry). */\n unprocessedKeys: ItemKey[];\n};\n\n/**\n * A single operation in a batch write request.\n */\nexport type BatchWriteOperation =\n | { type: \"put\"; item: Record<string, unknown> }\n | { type: \"delete\"; key: ItemKey };\n\n/**\n * The result of a batch write operation.\n */\nexport type BatchWriteResult = {\n /** Operations that could not be processed in this batch (caller should retry). */\n unprocessedOperations: BatchWriteOperation[];\n};\n","import { resolveConfig } from \"@celerity-sdk/config\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { DatastoreClient } from \"./types\";\nimport type { DynamoDBDatastoreConfig } from \"./providers/dynamodb/types\";\n\nexport type CreateDatastoreClientOptions = {\n /** Override provider selection. If omitted, derived from platform config. */\n provider?: \"aws\" | \"local\" | \"gcp\" | \"azure\";\n /** Cloud deploy target for local environments (e.g. \"aws\", \"gcloud\", \"azure\"). */\n deployTarget?: string;\n /** DynamoDB-specific configuration overrides. */\n aws?: DynamoDBDatastoreConfig;\n /** Optional tracer for Celerity-level span instrumentation. */\n tracer?: CelerityTracer;\n};\n\nexport async function createDatastoreClient(\n options?: CreateDatastoreClientOptions,\n): Promise<DatastoreClient> {\n const resolved = resolveConfig(\"datastore\");\n const provider = options?.provider ?? resolved.provider;\n\n switch (provider) {\n case \"aws\": {\n const { DynamoDBDatastoreClient } =\n await import(\"./providers/dynamodb/dynamodb-datastore-client.js\");\n return new DynamoDBDatastoreClient(options?.aws, options?.tracer);\n }\n case \"local\":\n return createLocalClient(options);\n default:\n throw new Error(`Unsupported datastore provider: \"${provider}\"`);\n }\n}\n\nasync function createLocalClient(options?: CreateDatastoreClientOptions): Promise<DatastoreClient> {\n const deployTarget = options?.deployTarget?.toLowerCase();\n\n switch (deployTarget) {\n case \"aws\":\n case \"aws-serverless\":\n case undefined: {\n // DynamoDB Local (v0 default when no deploy target is specified)\n const { captureDynamoDBConfig } = await import(\"./providers/dynamodb/config.js\");\n const { DynamoDBDatastoreClient } =\n await import(\"./providers/dynamodb/dynamodb-datastore-client.js\");\n const localConfig: DynamoDBDatastoreConfig = {\n ...captureDynamoDBConfig(),\n ...options?.aws,\n };\n return new DynamoDBDatastoreClient(localConfig, options?.tracer);\n }\n // case \"gcloud\":\n // case \"gcloud-serverless\":\n // v1: Firestore emulator\n // case \"azure\":\n // case \"azure-serverless\":\n // v1: Cosmos DB emulator\n default:\n throw new Error(\n `Unsupported local datastore deploy target: \"${deployTarget}\". Only AWS is supported in v0.`,\n );\n }\n}\n","import \"reflect-metadata\";\nimport { INJECT_METADATA, USE_RESOURCE_METADATA } from \"@celerity-sdk/common\";\nimport type { Datastore as DatastoreType } from \"./types\";\n\n// Re-declare as interface so the type merges with the decorator function below.\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface Datastore extends DatastoreType {}\n\nexport function datastoreToken(resourceName: string): symbol {\n return Symbol.for(`celerity:datastore:${resourceName}`);\n}\n\nexport const DEFAULT_DATASTORE_TOKEN = Symbol.for(\"celerity:datastore:default\");\n\n/**\n * Parameter decorator that injects a {@link Datastore} instance for the given\n * blueprint resource. Writes both DI injection metadata and CLI resource-ref\n * metadata using well-known `Symbol.for()` keys (no dependency on core).\n *\n * When `resourceName` is omitted, the default datastore token is used — this\n * auto-resolves when exactly one datastore resource exists.\n *\n * @example\n * ```ts\n * @Controller(\"/users\")\n * class UserController {\n * constructor(@Datastore(\"usersTable\") private users: Datastore) {}\n * }\n * ```\n */\nexport function Datastore(resourceName?: string): ParameterDecorator {\n return (target, _propertyKey, parameterIndex) => {\n const token = resourceName ? datastoreToken(resourceName) : DEFAULT_DATASTORE_TOKEN;\n const existing: Map<number, unknown> =\n Reflect.getOwnMetadata(INJECT_METADATA, target) ?? new Map();\n existing.set(parameterIndex, token);\n Reflect.defineMetadata(INJECT_METADATA, existing, target);\n\n if (resourceName) {\n const resources: string[] = Reflect.getOwnMetadata(USE_RESOURCE_METADATA, target) ?? [];\n if (!resources.includes(resourceName)) {\n Reflect.defineMetadata(USE_RESOURCE_METADATA, [...resources, resourceName], target);\n }\n }\n };\n}\n","import type { ServiceContainer } from \"@celerity-sdk/types\";\nimport type { Datastore } from \"./types\";\nimport { datastoreToken, DEFAULT_DATASTORE_TOKEN } from \"./decorators\";\n\n/**\n * Resolves a {@link Datastore} instance from the DI container.\n * For function-based handlers where parameter decorators aren't available.\n *\n * @param container - The service container (typically `context.container`).\n * @param resourceName - The blueprint resource name. Omit when exactly one\n * datastore resource exists to use the default.\n *\n * @example\n * ```ts\n * const handler = createHttpHandler(async (req, ctx) => {\n * const users = await getDatastore(ctx.container, \"usersTable\");\n * const user = await users.getItem({ pk: req.pathParameters.userId });\n * });\n * ```\n */\nexport function getDatastore(\n container: ServiceContainer,\n resourceName?: string,\n): Promise<Datastore> {\n const token = resourceName ? datastoreToken(resourceName) : DEFAULT_DATASTORE_TOKEN;\n return container.resolve<Datastore>(token);\n}\n","import createDebug from \"debug\";\nimport type { CelerityLayer, BaseHandlerContext, CelerityTracer } from \"@celerity-sdk/types\";\nimport { TRACER_TOKEN, CONFIG_SERVICE_TOKEN } from \"@celerity-sdk/common\";\nimport {\n type ConfigService,\n captureResourceLinks,\n getLinksOfType,\n RESOURCE_CONFIG_NAMESPACE,\n} from \"@celerity-sdk/config\";\nimport { createDatastoreClient } from \"./factory\";\nimport { datastoreToken, DEFAULT_DATASTORE_TOKEN } from \"./decorators\";\n\nconst debug = createDebug(\"celerity:datastore\");\n\n/**\n * System layer that auto-registers {@link DatastoreClient} and per-resource\n * {@link Datastore} handles in the DI container.\n *\n * Reads resource link topology from `CELERITY_RESOURCE_LINKS` and resolves\n * actual table/collection names from the ConfigService \"resources\" namespace.\n * Must run after ConfigLayer in the layer pipeline.\n */\ntype DatastoreLayerConfig = {\n deployTarget: string | undefined;\n};\n\nfunction captureDatastoreLayerConfig(): DatastoreLayerConfig {\n return {\n deployTarget: process.env.CELERITY_DEPLOY_TARGET,\n };\n}\n\nexport class DatastoreLayer implements CelerityLayer<BaseHandlerContext> {\n private initialized = false;\n private config: DatastoreLayerConfig | null = null;\n\n async handle(context: BaseHandlerContext, next: () => Promise<unknown>): Promise<unknown> {\n if (!this.initialized) {\n this.config = captureDatastoreLayerConfig();\n\n const tracer = context.container.has(TRACER_TOKEN)\n ? await context.container.resolve<CelerityTracer>(TRACER_TOKEN)\n : undefined;\n\n const client = await createDatastoreClient({\n tracer,\n deployTarget: this.config.deployTarget,\n });\n debug(\"registering DatastoreClient\");\n context.container.register(\"DatastoreClient\", { useValue: client });\n\n const links = captureResourceLinks();\n const datastoreLinks = getLinksOfType(links, \"datastore\");\n\n if (datastoreLinks.size > 0) {\n const configService = await context.container.resolve<ConfigService>(CONFIG_SERVICE_TOKEN);\n const resourceConfig = configService.namespace(RESOURCE_CONFIG_NAMESPACE);\n\n for (const [resourceName, configKey] of datastoreLinks) {\n const actualName = await resourceConfig.getOrThrow(configKey);\n debug(\"registered datastore resource %s → %s\", resourceName, actualName);\n context.container.register(datastoreToken(resourceName), {\n useValue: client.datastore(actualName),\n });\n }\n\n if (datastoreLinks.size === 1) {\n const [, configKey] = [...datastoreLinks.entries()][0];\n const actualName = await resourceConfig.getOrThrow(configKey);\n debug(\"registered default datastore → %s\", actualName);\n context.container.register(DEFAULT_DATASTORE_TOKEN, {\n useValue: client.datastore(actualName),\n });\n }\n }\n\n this.initialized = true;\n }\n\n return next();\n }\n}\n"],"mappings":"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","names":["DatastoreError","ConditionalCheckFailedError","Error","message","table","options","name","buildKeyConditionExpression","key","range","names","values","counter","pkName","pkValue","name","value","expression","skName","operator","skValue","COMPARISON_OPERATORS","lowVal","highVal","low","high","buildFilterExpression","conditions","buildExpressionNode","expr","depth","Array","isArray","buildGroup","isOrGroup","or","isAndGroup","and","buildSingleCondition","children","parts","map","child","length","joined","join","cond","i","attrName","valKey","fnName","eq","ne","lt","le","gt","ge","encodeCursor","lastEvaluatedKey","state","Buffer","from","JSON","stringify","toString","decodeCursor","cursor","parse","debug","DynamoDBItemListing","createDebug","_cursor","client","tableName","mode","options","tracer","Symbol","asyncIterator","cursorState","undefined","exclusiveStartKey","response","fetchPage","item","Items","LastEvaluatedKey","command","buildQueryCommand","buildScanCommand","doFetch","send","error","DatastoreError","cause","withSpan","opts","keyExpr","buildKeyConditionExpression","key","range","filterExpr","filter","buildFilterExpression","QueryCommand","TableName","IndexName","indexName","KeyConditionExpression","expression","FilterExpression","ExpressionAttributeNames","names","ExpressionAttributeValues","values","ScanIndexForward","sortAscending","Limit","maxResults","ExclusiveStartKey","ConsistentRead","consistentRead","ScanCommand","Object","keys","length","isConditionalCheckFailedError","error","Error","name","init_errors","import_debug","import_lib_dynamodb","debug","DynamoDBDatastore","init_errors","createDebug","tableName","client","tracer","getItem","key","options","traced","response","send","GetCommand","TableName","Key","ConsistentRead","consistentRead","Item","error","DatastoreError","cause","putItem","item","conditionParams","condition","buildFilterExpression","undefined","PutCommand","ConditionExpression","expression","ExpressionAttributeNames","names","ExpressionAttributeValues","values","isConditionalCheckFailedError","ConditionalCheckFailedError","deleteItem","DeleteCommand","query","name","DynamoDBItemListing","scan","batchGetItems","keys","length","BatchGetCommand","RequestItems","Keys","items","Responses","unprocessedKeys","UnprocessedKeys","batchWriteItems","operations","writeRequests","map","op","type","PutRequest","DeleteRequest","BatchWriteCommand","unprocessedRequests","UnprocessedItems","unprocessedOperations","req","attributes","fn","withSpan","span","captureDynamoDBConfig","region","process","env","AWS_REGION","AWS_DEFAULT_REGION","endpoint","CELERITY_AWS_DYNAMODB_ENDPOINT","AWS_ENDPOINT_URL","credentials","AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","accessKeyId","secretAccessKey","undefined","import_lib_dynamodb","DynamoDBDatastoreClient","client","docClient","config","tracer","captureDynamoDBConfig","datastore","name","DynamoDBDatastore","getDocClient","close","destroy","DynamoDBClient","region","endpoint","credentials","DynamoDBDocumentClient","from","marshallOptions","removeUndefinedValues","DatastoreClient","Symbol","for","import_config","createDatastoreClient","options","resolved","resolveConfig","provider","DynamoDBDatastoreClient","aws","tracer","createLocalClient","Error","deployTarget","toLowerCase","undefined","captureDynamoDBConfig","localConfig","datastoreToken","resourceName","Symbol","for","DEFAULT_DATASTORE_TOKEN","Datastore","target","_propertyKey","parameterIndex","token","existing","Reflect","getOwnMetadata","INJECT_METADATA","Map","set","defineMetadata","resources","USE_RESOURCE_METADATA","includes","getDatastore","container","resourceName","token","datastoreToken","DEFAULT_DATASTORE_TOKEN","resolve","import_debug","import_common","import_config","debug","createDebug","captureDatastoreLayerConfig","deployTarget","process","env","CELERITY_DEPLOY_TARGET","DatastoreLayer","initialized","config","handle","context","next","tracer","container","has","TRACER_TOKEN","resolve","undefined","client","createDatastoreClient","register","useValue","links","captureResourceLinks","datastoreLinks","getLinksOfType","size","configService","CONFIG_SERVICE_TOKEN","resourceConfig","namespace","RESOURCE_CONFIG_NAMESPACE","resourceName","configKey","actualName","getOrThrow","datastoreToken","datastore","entries","DEFAULT_DATASTORE_TOKEN"]}
package/dist/index.d.ts CHANGED
@@ -171,10 +171,23 @@ type Condition = {
171
171
  operator: "exists";
172
172
  });
173
173
  /**
174
- * One or more conditions AND'd together. A single {@link Condition} or an array
175
- * of Conditions — when multiple are provided, all must be true.
174
+ * A group of conditions combined with AND logic. All conditions must be true.
176
175
  */
177
- type ConditionExpression = Condition | Condition[];
176
+ type AndGroup = {
177
+ and: ConditionExpression[];
178
+ };
179
+ /**
180
+ * A group of conditions combined with OR logic. At least one condition must be true.
181
+ */
182
+ type OrGroup = {
183
+ or: ConditionExpression[];
184
+ };
185
+ /**
186
+ * One or more conditions combined with logical operators. A single {@link Condition},
187
+ * an array of Conditions (implicit AND), or explicit
188
+ * {@link AndGroup}/{@link OrGroup} for compound logic with recursive nesting.
189
+ */
190
+ type ConditionExpression = Condition | Condition[] | AndGroup | OrGroup;
178
191
  /**
179
192
  * Options for the getItem operation.
180
193
  */
@@ -368,4 +381,4 @@ declare class ConditionalCheckFailedError extends DatastoreError {
368
381
  });
369
382
  }
370
383
 
371
- export { type BatchGetItemsOptions, type BatchGetResult, type BatchWriteOperation, type BatchWriteResult, type Condition, type ConditionExpression, ConditionalCheckFailedError, type CreateDatastoreClientOptions, DEFAULT_DATASTORE_TOKEN, Datastore, DatastoreClient, DatastoreError, DatastoreLayer, type DeleteItemOptions, type DynamoDBDatastoreConfig, type GetItemOptions, type ItemKey, type ItemListing, type KeyCondition, type PutItemOptions, type QueryOptions, type RangeCondition, type ScanOptions, createDatastoreClient, datastoreToken, getDatastore };
384
+ export { type AndGroup, type BatchGetItemsOptions, type BatchGetResult, type BatchWriteOperation, type BatchWriteResult, type Condition, type ConditionExpression, ConditionalCheckFailedError, type CreateDatastoreClientOptions, DEFAULT_DATASTORE_TOKEN, Datastore, DatastoreClient, DatastoreError, DatastoreLayer, type DeleteItemOptions, type DynamoDBDatastoreConfig, type GetItemOptions, type ItemKey, type ItemListing, type KeyCondition, type OrGroup, type PutItemOptions, type QueryOptions, type RangeCondition, type ScanOptions, createDatastoreClient, datastoreToken, getDatastore };
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ async function createDatastoreClient(options) {
16
16
  const provider = options?.provider ?? resolved.provider;
17
17
  switch (provider) {
18
18
  case "aws": {
19
- const { DynamoDBDatastoreClient } = await import("./dynamodb-datastore-client-LQH3GS6X.js");
19
+ const { DynamoDBDatastoreClient } = await import("./dynamodb-datastore-client-RLOVW5ZU.js");
20
20
  return new DynamoDBDatastoreClient(options?.aws, options?.tracer);
21
21
  }
22
22
  case "local":
@@ -33,7 +33,7 @@ async function createLocalClient(options) {
33
33
  case "aws-serverless":
34
34
  case void 0: {
35
35
  const { captureDynamoDBConfig } = await import("./config-IXTAYSFF.js");
36
- const { DynamoDBDatastoreClient } = await import("./dynamodb-datastore-client-LQH3GS6X.js");
36
+ const { DynamoDBDatastoreClient } = await import("./dynamodb-datastore-client-RLOVW5ZU.js");
37
37
  const localConfig = {
38
38
  ...captureDynamoDBConfig(),
39
39
  ...options?.aws
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/factory.ts","../src/decorators.ts","../src/helpers.ts","../src/layer.ts"],"sourcesContent":["import type { Closeable } from \"@celerity-sdk/types\";\n\nexport const DatastoreClient = Symbol.for(\"DatastoreClient\");\n\n/**\n * A data store client abstraction for NoSQL databases. Provides access to named\n * data stores (tables/collections), each representing a logical container for items.\n */\nexport interface DatastoreClient extends Closeable {\n /**\n * Retrieves a datastore instance by its logical name. The returned datastore\n * is a lightweight handle — no network calls are made until an operation is invoked.\n *\n * @param name The name of the datastore (table/collection).\n */\n datastore(name: string): Datastore;\n}\n\n/**\n * A datastore represents a logical container (table/collection) for items in a\n * NoSQL data store. It provides methods for performing CRUD operations, queries,\n * scans, and batch operations within the data store.\n */\nexport interface Datastore {\n /**\n * Retrieve an item from the data store by its primary key. Returns `null` if the\n * item does not exist.\n *\n * @param key The primary key attributes identifying the item.\n * @param options Optional parameters such as consistent read.\n * @returns A promise that resolves to the item, or `null` if not found.\n */\n getItem<T = Record<string, unknown>>(key: ItemKey, options?: GetItemOptions): Promise<T | null>;\n\n /**\n * Store an item in the data store. If an item with the same primary key already\n * exists, it is replaced entirely (upsert semantics).\n *\n * @param item The item to store. Must include all primary key attributes.\n * @param options Optional parameters such as condition expressions.\n */\n putItem(item: Record<string, unknown>, options?: PutItemOptions): Promise<void>;\n\n /**\n * Delete an item from the data store by its primary key. This operation is\n * idempotent — deleting a non-existent key does not throw.\n *\n * @param key The primary key attributes identifying the item to delete.\n * @param options Optional parameters such as condition expressions.\n */\n deleteItem(key: ItemKey, options?: DeleteItemOptions): Promise<void>;\n\n /**\n * Query items by primary key with optional range conditions. Returns an\n * {@link ItemListing} that handles pagination transparently, allowing the caller\n * to iterate over all matching items without managing page tokens.\n *\n * @param options Query parameters including key condition, range conditions,\n * filters, and pagination controls.\n * @returns An item listing that yields items and exposes a cursor for resuming.\n */\n query<T = Record<string, unknown>>(options: QueryOptions): ItemListing<T>;\n\n /**\n * Perform a full scan of the data store. Returns an {@link ItemListing} that\n * handles pagination transparently. Scans read every item in the table and\n * should be used sparingly.\n *\n * @param options Optional scan parameters such as filters and pagination controls.\n * @returns An item listing that yields items and exposes a cursor for resuming.\n */\n scan<T = Record<string, unknown>>(options?: ScanOptions): ItemListing<T>;\n\n /**\n * Retrieve multiple items by their primary keys in a single batch operation.\n * The batch may be split into multiple requests if it exceeds provider limits.\n *\n * @param keys The primary keys of the items to retrieve.\n * @param options Optional parameters such as consistent read.\n * @returns A promise that resolves to the batch get result, including retrieved\n * items and any unprocessed keys.\n */\n batchGetItems<T = Record<string, unknown>>(\n keys: ItemKey[],\n options?: BatchGetItemsOptions,\n ): Promise<BatchGetResult<T>>;\n\n /**\n * Perform multiple put and delete operations in a single batch. The batch may\n * be split into multiple requests if it exceeds provider limits.\n *\n * @param operations The batch of put and delete operations to execute.\n * @returns A promise that resolves to the batch write result, including any\n * unprocessed operations.\n */\n batchWriteItems(operations: BatchWriteOperation[]): Promise<BatchWriteResult>;\n}\n\n/**\n * Primary key attributes for an item. Keys can be string or number values\n * corresponding to primary key and optional range key attributes.\n */\nexport type ItemKey = Record<string, string | number>;\n\n/**\n * A condition on the primary key — always an equality match.\n */\nexport type KeyCondition = {\n /** The attribute name of the primary key. */\n name: string;\n /** The primary key value to match. */\n value: string | number;\n};\n\n/**\n * A condition on the range key. Supports equality, comparison, range,\n * and prefix matching operations.\n */\nexport type RangeCondition = {\n /** The attribute name of the range key. */\n name: string;\n} & (\n | { operator: \"eq\"; value: string | number }\n | { operator: \"lt\"; value: string | number }\n | { operator: \"le\"; value: string | number }\n | { operator: \"gt\"; value: string | number }\n | { operator: \"ge\"; value: string | number }\n | { operator: \"between\"; low: string | number; high: string | number }\n | { operator: \"startsWith\"; value: string }\n);\n\n/**\n * A filter condition on an item attribute. Used for post-read filtering\n * in queries and scans, and for conditional writes.\n *\n * Only includes operators that map cleanly across all target providers\n * (DynamoDB, Firestore, Cosmos DB). The `not_exists` operator is\n * provider-specific and available through the concrete provider classes.\n */\nexport type Condition = {\n /** The attribute name to evaluate. */\n name: string;\n} & (\n | { operator: \"eq\"; value: unknown }\n | { operator: \"ne\"; value: unknown }\n | { operator: \"lt\"; value: string | number }\n | { operator: \"le\"; value: string | number }\n | { operator: \"gt\"; value: string | number }\n | { operator: \"ge\"; value: string | number }\n | { operator: \"between\"; low: string | number; high: string | number }\n | { operator: \"startsWith\"; value: string }\n | { operator: \"contains\"; value: string | number }\n | { operator: \"exists\" }\n);\n\n/**\n * One or more conditions AND'd together. A single {@link Condition} or an array\n * of Conditions — when multiple are provided, all must be true.\n */\nexport type ConditionExpression = Condition | Condition[];\n\n/**\n * Options for the getItem operation.\n */\nexport type GetItemOptions = {\n /** When true, performs a strongly consistent read. Default is eventually consistent. */\n consistentRead?: boolean;\n};\n\n/**\n * Options for the putItem operation.\n */\nexport type PutItemOptions = {\n /**\n * Condition that must be met for the put to succeed. Throws\n * {@link ConditionalCheckFailedError} if the condition is not met.\n */\n condition?: ConditionExpression;\n};\n\n/**\n * Options for the deleteItem operation.\n */\nexport type DeleteItemOptions = {\n /**\n * Condition that must be met for the delete to succeed. Throws\n * {@link ConditionalCheckFailedError} if the condition is not met.\n */\n condition?: ConditionExpression;\n};\n\n/**\n * Options for the query operation.\n */\nexport type QueryOptions = {\n /** The primary key condition (required for queries). */\n key: KeyCondition;\n /** Optional range key condition to narrow the query range. */\n range?: RangeCondition;\n /** Optional filter conditions applied after the query read (does not reduce read capacity). */\n filter?: ConditionExpression;\n /** Query an index instead of the base table. */\n indexName?: string;\n /** When true, results are returned in ascending key order (default). Set to false for descending. */\n sortAscending?: boolean;\n /** Maximum number of items to return per internal page fetch. */\n maxResults?: number;\n /** Opaque cursor token to resume a previous query from where it left off. */\n cursor?: string;\n /** When true, performs a strongly consistent read (not supported on secondary indexes). */\n consistentRead?: boolean;\n};\n\n/**\n * Options for the scan operation.\n */\nexport type ScanOptions = {\n /** Optional filter conditions applied after the scan read. */\n filter?: ConditionExpression;\n /** Scan an index instead of the base table. */\n indexName?: string;\n /** Maximum number of items to return per internal page fetch. */\n maxResults?: number;\n /** Opaque cursor token to resume a previous scan from where it left off. */\n cursor?: string;\n /** When true, performs a strongly consistent read. */\n consistentRead?: boolean;\n};\n\n/**\n * An async iterable of items that also exposes a cursor token for resuming\n * iteration from the current position. The cursor is updated as pages are fetched\n * and encodes enough state to resume from the exact position across all providers.\n */\nexport interface ItemListing<T> extends AsyncIterable<T> {\n /**\n * A cursor token representing the current position in the listing. This token\n * can be passed to a subsequent query or scan call to resume iteration from\n * this position. The value is `undefined` before iteration begins or after all\n * items have been yielded.\n */\n readonly cursor: string | undefined;\n}\n\n/**\n * Options for the batchGetItems operation.\n */\nexport type BatchGetItemsOptions = {\n /** When true, performs strongly consistent reads for all items. */\n consistentRead?: boolean;\n};\n\n/**\n * The result of a batch get operation.\n */\nexport type BatchGetResult<T> = {\n /** The successfully retrieved items. */\n items: T[];\n /** Keys that could not be processed in this batch (caller should retry). */\n unprocessedKeys: ItemKey[];\n};\n\n/**\n * A single operation in a batch write request.\n */\nexport type BatchWriteOperation =\n | { type: \"put\"; item: Record<string, unknown> }\n | { type: \"delete\"; key: ItemKey };\n\n/**\n * The result of a batch write operation.\n */\nexport type BatchWriteResult = {\n /** Operations that could not be processed in this batch (caller should retry). */\n unprocessedOperations: BatchWriteOperation[];\n};\n","import { resolveConfig } from \"@celerity-sdk/config\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { DatastoreClient } from \"./types\";\nimport type { DynamoDBDatastoreConfig } from \"./providers/dynamodb/types\";\n\nexport type CreateDatastoreClientOptions = {\n /** Override provider selection. If omitted, derived from platform config. */\n provider?: \"aws\" | \"local\" | \"gcp\" | \"azure\";\n /** Cloud deploy target for local environments (e.g. \"aws\", \"gcloud\", \"azure\"). */\n deployTarget?: string;\n /** DynamoDB-specific configuration overrides. */\n aws?: DynamoDBDatastoreConfig;\n /** Optional tracer for Celerity-level span instrumentation. */\n tracer?: CelerityTracer;\n};\n\nexport async function createDatastoreClient(\n options?: CreateDatastoreClientOptions,\n): Promise<DatastoreClient> {\n const resolved = resolveConfig(\"datastore\");\n const provider = options?.provider ?? resolved.provider;\n\n switch (provider) {\n case \"aws\": {\n const { DynamoDBDatastoreClient } =\n await import(\"./providers/dynamodb/dynamodb-datastore-client.js\");\n return new DynamoDBDatastoreClient(options?.aws, options?.tracer);\n }\n case \"local\":\n return createLocalClient(options);\n default:\n throw new Error(`Unsupported datastore provider: \"${provider}\"`);\n }\n}\n\nasync function createLocalClient(options?: CreateDatastoreClientOptions): Promise<DatastoreClient> {\n const deployTarget = options?.deployTarget?.toLowerCase();\n\n switch (deployTarget) {\n case \"aws\":\n case \"aws-serverless\":\n case undefined: {\n // DynamoDB Local (v0 default when no deploy target is specified)\n const { captureDynamoDBConfig } = await import(\"./providers/dynamodb/config.js\");\n const { DynamoDBDatastoreClient } =\n await import(\"./providers/dynamodb/dynamodb-datastore-client.js\");\n const localConfig: DynamoDBDatastoreConfig = {\n ...captureDynamoDBConfig(),\n ...options?.aws,\n };\n return new DynamoDBDatastoreClient(localConfig, options?.tracer);\n }\n // case \"gcloud\":\n // case \"gcloud-serverless\":\n // v1: Firestore emulator\n // case \"azure\":\n // case \"azure-serverless\":\n // v1: Cosmos DB emulator\n default:\n throw new Error(\n `Unsupported local datastore deploy target: \"${deployTarget}\". Only AWS is supported in v0.`,\n );\n }\n}\n","import \"reflect-metadata\";\nimport { INJECT_METADATA, USE_RESOURCE_METADATA } from \"@celerity-sdk/common\";\nimport type { Datastore as DatastoreType } from \"./types\";\n\n// Re-declare as interface so the type merges with the decorator function below.\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface Datastore extends DatastoreType {}\n\nexport function datastoreToken(resourceName: string): symbol {\n return Symbol.for(`celerity:datastore:${resourceName}`);\n}\n\nexport const DEFAULT_DATASTORE_TOKEN = Symbol.for(\"celerity:datastore:default\");\n\n/**\n * Parameter decorator that injects a {@link Datastore} instance for the given\n * blueprint resource. Writes both DI injection metadata and CLI resource-ref\n * metadata using well-known `Symbol.for()` keys (no dependency on core).\n *\n * When `resourceName` is omitted, the default datastore token is used — this\n * auto-resolves when exactly one datastore resource exists.\n *\n * @example\n * ```ts\n * @Controller(\"/users\")\n * class UserController {\n * constructor(@Datastore(\"usersTable\") private users: Datastore) {}\n * }\n * ```\n */\nexport function Datastore(resourceName?: string): ParameterDecorator {\n return (target, _propertyKey, parameterIndex) => {\n const token = resourceName ? datastoreToken(resourceName) : DEFAULT_DATASTORE_TOKEN;\n const existing: Map<number, unknown> =\n Reflect.getOwnMetadata(INJECT_METADATA, target) ?? new Map();\n existing.set(parameterIndex, token);\n Reflect.defineMetadata(INJECT_METADATA, existing, target);\n\n if (resourceName) {\n const resources: string[] = Reflect.getOwnMetadata(USE_RESOURCE_METADATA, target) ?? [];\n if (!resources.includes(resourceName)) {\n Reflect.defineMetadata(USE_RESOURCE_METADATA, [...resources, resourceName], target);\n }\n }\n };\n}\n","import type { ServiceContainer } from \"@celerity-sdk/types\";\nimport type { Datastore } from \"./types\";\nimport { datastoreToken, DEFAULT_DATASTORE_TOKEN } from \"./decorators\";\n\n/**\n * Resolves a {@link Datastore} instance from the DI container.\n * For function-based handlers where parameter decorators aren't available.\n *\n * @param container - The service container (typically `context.container`).\n * @param resourceName - The blueprint resource name. Omit when exactly one\n * datastore resource exists to use the default.\n *\n * @example\n * ```ts\n * const handler = createHttpHandler(async (req, ctx) => {\n * const users = await getDatastore(ctx.container, \"usersTable\");\n * const user = await users.getItem({ pk: req.pathParameters.userId });\n * });\n * ```\n */\nexport function getDatastore(\n container: ServiceContainer,\n resourceName?: string,\n): Promise<Datastore> {\n const token = resourceName ? datastoreToken(resourceName) : DEFAULT_DATASTORE_TOKEN;\n return container.resolve<Datastore>(token);\n}\n","import createDebug from \"debug\";\nimport type { CelerityLayer, BaseHandlerContext, CelerityTracer } from \"@celerity-sdk/types\";\nimport { TRACER_TOKEN, CONFIG_SERVICE_TOKEN } from \"@celerity-sdk/common\";\nimport {\n type ConfigService,\n captureResourceLinks,\n getLinksOfType,\n RESOURCE_CONFIG_NAMESPACE,\n} from \"@celerity-sdk/config\";\nimport { createDatastoreClient } from \"./factory\";\nimport { datastoreToken, DEFAULT_DATASTORE_TOKEN } from \"./decorators\";\n\nconst debug = createDebug(\"celerity:datastore\");\n\n/**\n * System layer that auto-registers {@link DatastoreClient} and per-resource\n * {@link Datastore} handles in the DI container.\n *\n * Reads resource link topology from `CELERITY_RESOURCE_LINKS` and resolves\n * actual table/collection names from the ConfigService \"resources\" namespace.\n * Must run after ConfigLayer in the layer pipeline.\n */\ntype DatastoreLayerConfig = {\n deployTarget: string | undefined;\n};\n\nfunction captureDatastoreLayerConfig(): DatastoreLayerConfig {\n return {\n deployTarget: process.env.CELERITY_DEPLOY_TARGET,\n };\n}\n\nexport class DatastoreLayer implements CelerityLayer<BaseHandlerContext> {\n private initialized = false;\n private config: DatastoreLayerConfig | null = null;\n\n async handle(context: BaseHandlerContext, next: () => Promise<unknown>): Promise<unknown> {\n if (!this.initialized) {\n this.config = captureDatastoreLayerConfig();\n\n const tracer = context.container.has(TRACER_TOKEN)\n ? await context.container.resolve<CelerityTracer>(TRACER_TOKEN)\n : undefined;\n\n const client = await createDatastoreClient({\n tracer,\n deployTarget: this.config.deployTarget,\n });\n debug(\"registering DatastoreClient\");\n context.container.register(\"DatastoreClient\", { useValue: client });\n\n const links = captureResourceLinks();\n const datastoreLinks = getLinksOfType(links, \"datastore\");\n\n if (datastoreLinks.size > 0) {\n const configService = await context.container.resolve<ConfigService>(CONFIG_SERVICE_TOKEN);\n const resourceConfig = configService.namespace(RESOURCE_CONFIG_NAMESPACE);\n\n for (const [resourceName, configKey] of datastoreLinks) {\n const actualName = await resourceConfig.getOrThrow(configKey);\n debug(\"registered datastore resource %s → %s\", resourceName, actualName);\n context.container.register(datastoreToken(resourceName), {\n useValue: client.datastore(actualName),\n });\n }\n\n if (datastoreLinks.size === 1) {\n const [, configKey] = [...datastoreLinks.entries()][0];\n const actualName = await resourceConfig.getOrThrow(configKey);\n debug(\"registered default datastore → %s\", actualName);\n context.container.register(DEFAULT_DATASTORE_TOKEN, {\n useValue: client.datastore(actualName),\n });\n }\n }\n\n this.initialized = true;\n }\n\n return next();\n }\n}\n"],"mappings":"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","names":["DatastoreClient","Symbol","for","resolveConfig","createDatastoreClient","options","resolved","resolveConfig","provider","DynamoDBDatastoreClient","aws","tracer","createLocalClient","Error","deployTarget","toLowerCase","undefined","captureDynamoDBConfig","localConfig","INJECT_METADATA","USE_RESOURCE_METADATA","datastoreToken","resourceName","Symbol","for","DEFAULT_DATASTORE_TOKEN","Datastore","target","_propertyKey","parameterIndex","token","existing","Reflect","getOwnMetadata","INJECT_METADATA","Map","set","defineMetadata","resources","USE_RESOURCE_METADATA","includes","getDatastore","container","resourceName","token","datastoreToken","DEFAULT_DATASTORE_TOKEN","resolve","createDebug","TRACER_TOKEN","CONFIG_SERVICE_TOKEN","captureResourceLinks","getLinksOfType","RESOURCE_CONFIG_NAMESPACE","debug","createDebug","captureDatastoreLayerConfig","deployTarget","process","env","CELERITY_DEPLOY_TARGET","DatastoreLayer","initialized","config","handle","context","next","tracer","container","has","TRACER_TOKEN","resolve","undefined","client","createDatastoreClient","register","useValue","links","captureResourceLinks","datastoreLinks","getLinksOfType","size","configService","CONFIG_SERVICE_TOKEN","resourceConfig","namespace","RESOURCE_CONFIG_NAMESPACE","resourceName","configKey","actualName","getOrThrow","datastoreToken","datastore","entries","DEFAULT_DATASTORE_TOKEN"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/factory.ts","../src/decorators.ts","../src/helpers.ts","../src/layer.ts"],"sourcesContent":["import type { Closeable } from \"@celerity-sdk/types\";\n\nexport const DatastoreClient = Symbol.for(\"DatastoreClient\");\n\n/**\n * A data store client abstraction for NoSQL databases. Provides access to named\n * data stores (tables/collections), each representing a logical container for items.\n */\nexport interface DatastoreClient extends Closeable {\n /**\n * Retrieves a datastore instance by its logical name. The returned datastore\n * is a lightweight handle — no network calls are made until an operation is invoked.\n *\n * @param name The name of the datastore (table/collection).\n */\n datastore(name: string): Datastore;\n}\n\n/**\n * A datastore represents a logical container (table/collection) for items in a\n * NoSQL data store. It provides methods for performing CRUD operations, queries,\n * scans, and batch operations within the data store.\n */\nexport interface Datastore {\n /**\n * Retrieve an item from the data store by its primary key. Returns `null` if the\n * item does not exist.\n *\n * @param key The primary key attributes identifying the item.\n * @param options Optional parameters such as consistent read.\n * @returns A promise that resolves to the item, or `null` if not found.\n */\n getItem<T = Record<string, unknown>>(key: ItemKey, options?: GetItemOptions): Promise<T | null>;\n\n /**\n * Store an item in the data store. If an item with the same primary key already\n * exists, it is replaced entirely (upsert semantics).\n *\n * @param item The item to store. Must include all primary key attributes.\n * @param options Optional parameters such as condition expressions.\n */\n putItem(item: Record<string, unknown>, options?: PutItemOptions): Promise<void>;\n\n /**\n * Delete an item from the data store by its primary key. This operation is\n * idempotent — deleting a non-existent key does not throw.\n *\n * @param key The primary key attributes identifying the item to delete.\n * @param options Optional parameters such as condition expressions.\n */\n deleteItem(key: ItemKey, options?: DeleteItemOptions): Promise<void>;\n\n /**\n * Query items by primary key with optional range conditions. Returns an\n * {@link ItemListing} that handles pagination transparently, allowing the caller\n * to iterate over all matching items without managing page tokens.\n *\n * @param options Query parameters including key condition, range conditions,\n * filters, and pagination controls.\n * @returns An item listing that yields items and exposes a cursor for resuming.\n */\n query<T = Record<string, unknown>>(options: QueryOptions): ItemListing<T>;\n\n /**\n * Perform a full scan of the data store. Returns an {@link ItemListing} that\n * handles pagination transparently. Scans read every item in the table and\n * should be used sparingly.\n *\n * @param options Optional scan parameters such as filters and pagination controls.\n * @returns An item listing that yields items and exposes a cursor for resuming.\n */\n scan<T = Record<string, unknown>>(options?: ScanOptions): ItemListing<T>;\n\n /**\n * Retrieve multiple items by their primary keys in a single batch operation.\n * The batch may be split into multiple requests if it exceeds provider limits.\n *\n * @param keys The primary keys of the items to retrieve.\n * @param options Optional parameters such as consistent read.\n * @returns A promise that resolves to the batch get result, including retrieved\n * items and any unprocessed keys.\n */\n batchGetItems<T = Record<string, unknown>>(\n keys: ItemKey[],\n options?: BatchGetItemsOptions,\n ): Promise<BatchGetResult<T>>;\n\n /**\n * Perform multiple put and delete operations in a single batch. The batch may\n * be split into multiple requests if it exceeds provider limits.\n *\n * @param operations The batch of put and delete operations to execute.\n * @returns A promise that resolves to the batch write result, including any\n * unprocessed operations.\n */\n batchWriteItems(operations: BatchWriteOperation[]): Promise<BatchWriteResult>;\n}\n\n/**\n * Primary key attributes for an item. Keys can be string or number values\n * corresponding to primary key and optional range key attributes.\n */\nexport type ItemKey = Record<string, string | number>;\n\n/**\n * A condition on the primary key — always an equality match.\n */\nexport type KeyCondition = {\n /** The attribute name of the primary key. */\n name: string;\n /** The primary key value to match. */\n value: string | number;\n};\n\n/**\n * A condition on the range key. Supports equality, comparison, range,\n * and prefix matching operations.\n */\nexport type RangeCondition = {\n /** The attribute name of the range key. */\n name: string;\n} & (\n | { operator: \"eq\"; value: string | number }\n | { operator: \"lt\"; value: string | number }\n | { operator: \"le\"; value: string | number }\n | { operator: \"gt\"; value: string | number }\n | { operator: \"ge\"; value: string | number }\n | { operator: \"between\"; low: string | number; high: string | number }\n | { operator: \"startsWith\"; value: string }\n);\n\n/**\n * A filter condition on an item attribute. Used for post-read filtering\n * in queries and scans, and for conditional writes.\n *\n * Only includes operators that map cleanly across all target providers\n * (DynamoDB, Firestore, Cosmos DB). The `not_exists` operator is\n * provider-specific and available through the concrete provider classes.\n */\nexport type Condition = {\n /** The attribute name to evaluate. */\n name: string;\n} & (\n | { operator: \"eq\"; value: unknown }\n | { operator: \"ne\"; value: unknown }\n | { operator: \"lt\"; value: string | number }\n | { operator: \"le\"; value: string | number }\n | { operator: \"gt\"; value: string | number }\n | { operator: \"ge\"; value: string | number }\n | { operator: \"between\"; low: string | number; high: string | number }\n | { operator: \"startsWith\"; value: string }\n | { operator: \"contains\"; value: string | number }\n | { operator: \"exists\" }\n);\n\n/**\n * A group of conditions combined with AND logic. All conditions must be true.\n */\nexport type AndGroup = { and: ConditionExpression[] };\n\n/**\n * A group of conditions combined with OR logic. At least one condition must be true.\n */\nexport type OrGroup = { or: ConditionExpression[] };\n\n/**\n * One or more conditions combined with logical operators. A single {@link Condition},\n * an array of Conditions (implicit AND), or explicit\n * {@link AndGroup}/{@link OrGroup} for compound logic with recursive nesting.\n */\nexport type ConditionExpression = Condition | Condition[] | AndGroup | OrGroup;\n\n/**\n * Options for the getItem operation.\n */\nexport type GetItemOptions = {\n /** When true, performs a strongly consistent read. Default is eventually consistent. */\n consistentRead?: boolean;\n};\n\n/**\n * Options for the putItem operation.\n */\nexport type PutItemOptions = {\n /**\n * Condition that must be met for the put to succeed. Throws\n * {@link ConditionalCheckFailedError} if the condition is not met.\n */\n condition?: ConditionExpression;\n};\n\n/**\n * Options for the deleteItem operation.\n */\nexport type DeleteItemOptions = {\n /**\n * Condition that must be met for the delete to succeed. Throws\n * {@link ConditionalCheckFailedError} if the condition is not met.\n */\n condition?: ConditionExpression;\n};\n\n/**\n * Options for the query operation.\n */\nexport type QueryOptions = {\n /** The primary key condition (required for queries). */\n key: KeyCondition;\n /** Optional range key condition to narrow the query range. */\n range?: RangeCondition;\n /** Optional filter conditions applied after the query read (does not reduce read capacity). */\n filter?: ConditionExpression;\n /** Query an index instead of the base table. */\n indexName?: string;\n /** When true, results are returned in ascending key order (default). Set to false for descending. */\n sortAscending?: boolean;\n /** Maximum number of items to return per internal page fetch. */\n maxResults?: number;\n /** Opaque cursor token to resume a previous query from where it left off. */\n cursor?: string;\n /** When true, performs a strongly consistent read (not supported on secondary indexes). */\n consistentRead?: boolean;\n};\n\n/**\n * Options for the scan operation.\n */\nexport type ScanOptions = {\n /** Optional filter conditions applied after the scan read. */\n filter?: ConditionExpression;\n /** Scan an index instead of the base table. */\n indexName?: string;\n /** Maximum number of items to return per internal page fetch. */\n maxResults?: number;\n /** Opaque cursor token to resume a previous scan from where it left off. */\n cursor?: string;\n /** When true, performs a strongly consistent read. */\n consistentRead?: boolean;\n};\n\n/**\n * An async iterable of items that also exposes a cursor token for resuming\n * iteration from the current position. The cursor is updated as pages are fetched\n * and encodes enough state to resume from the exact position across all providers.\n */\nexport interface ItemListing<T> extends AsyncIterable<T> {\n /**\n * A cursor token representing the current position in the listing. This token\n * can be passed to a subsequent query or scan call to resume iteration from\n * this position. The value is `undefined` before iteration begins or after all\n * items have been yielded.\n */\n readonly cursor: string | undefined;\n}\n\n/**\n * Options for the batchGetItems operation.\n */\nexport type BatchGetItemsOptions = {\n /** When true, performs strongly consistent reads for all items. */\n consistentRead?: boolean;\n};\n\n/**\n * The result of a batch get operation.\n */\nexport type BatchGetResult<T> = {\n /** The successfully retrieved items. */\n items: T[];\n /** Keys that could not be processed in this batch (caller should retry). */\n unprocessedKeys: ItemKey[];\n};\n\n/**\n * A single operation in a batch write request.\n */\nexport type BatchWriteOperation =\n | { type: \"put\"; item: Record<string, unknown> }\n | { type: \"delete\"; key: ItemKey };\n\n/**\n * The result of a batch write operation.\n */\nexport type BatchWriteResult = {\n /** Operations that could not be processed in this batch (caller should retry). */\n unprocessedOperations: BatchWriteOperation[];\n};\n","import { resolveConfig } from \"@celerity-sdk/config\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { DatastoreClient } from \"./types\";\nimport type { DynamoDBDatastoreConfig } from \"./providers/dynamodb/types\";\n\nexport type CreateDatastoreClientOptions = {\n /** Override provider selection. If omitted, derived from platform config. */\n provider?: \"aws\" | \"local\" | \"gcp\" | \"azure\";\n /** Cloud deploy target for local environments (e.g. \"aws\", \"gcloud\", \"azure\"). */\n deployTarget?: string;\n /** DynamoDB-specific configuration overrides. */\n aws?: DynamoDBDatastoreConfig;\n /** Optional tracer for Celerity-level span instrumentation. */\n tracer?: CelerityTracer;\n};\n\nexport async function createDatastoreClient(\n options?: CreateDatastoreClientOptions,\n): Promise<DatastoreClient> {\n const resolved = resolveConfig(\"datastore\");\n const provider = options?.provider ?? resolved.provider;\n\n switch (provider) {\n case \"aws\": {\n const { DynamoDBDatastoreClient } =\n await import(\"./providers/dynamodb/dynamodb-datastore-client.js\");\n return new DynamoDBDatastoreClient(options?.aws, options?.tracer);\n }\n case \"local\":\n return createLocalClient(options);\n default:\n throw new Error(`Unsupported datastore provider: \"${provider}\"`);\n }\n}\n\nasync function createLocalClient(options?: CreateDatastoreClientOptions): Promise<DatastoreClient> {\n const deployTarget = options?.deployTarget?.toLowerCase();\n\n switch (deployTarget) {\n case \"aws\":\n case \"aws-serverless\":\n case undefined: {\n // DynamoDB Local (v0 default when no deploy target is specified)\n const { captureDynamoDBConfig } = await import(\"./providers/dynamodb/config.js\");\n const { DynamoDBDatastoreClient } =\n await import(\"./providers/dynamodb/dynamodb-datastore-client.js\");\n const localConfig: DynamoDBDatastoreConfig = {\n ...captureDynamoDBConfig(),\n ...options?.aws,\n };\n return new DynamoDBDatastoreClient(localConfig, options?.tracer);\n }\n // case \"gcloud\":\n // case \"gcloud-serverless\":\n // v1: Firestore emulator\n // case \"azure\":\n // case \"azure-serverless\":\n // v1: Cosmos DB emulator\n default:\n throw new Error(\n `Unsupported local datastore deploy target: \"${deployTarget}\". Only AWS is supported in v0.`,\n );\n }\n}\n","import \"reflect-metadata\";\nimport { INJECT_METADATA, USE_RESOURCE_METADATA } from \"@celerity-sdk/common\";\nimport type { Datastore as DatastoreType } from \"./types\";\n\n// Re-declare as interface so the type merges with the decorator function below.\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface Datastore extends DatastoreType {}\n\nexport function datastoreToken(resourceName: string): symbol {\n return Symbol.for(`celerity:datastore:${resourceName}`);\n}\n\nexport const DEFAULT_DATASTORE_TOKEN = Symbol.for(\"celerity:datastore:default\");\n\n/**\n * Parameter decorator that injects a {@link Datastore} instance for the given\n * blueprint resource. Writes both DI injection metadata and CLI resource-ref\n * metadata using well-known `Symbol.for()` keys (no dependency on core).\n *\n * When `resourceName` is omitted, the default datastore token is used — this\n * auto-resolves when exactly one datastore resource exists.\n *\n * @example\n * ```ts\n * @Controller(\"/users\")\n * class UserController {\n * constructor(@Datastore(\"usersTable\") private users: Datastore) {}\n * }\n * ```\n */\nexport function Datastore(resourceName?: string): ParameterDecorator {\n return (target, _propertyKey, parameterIndex) => {\n const token = resourceName ? datastoreToken(resourceName) : DEFAULT_DATASTORE_TOKEN;\n const existing: Map<number, unknown> =\n Reflect.getOwnMetadata(INJECT_METADATA, target) ?? new Map();\n existing.set(parameterIndex, token);\n Reflect.defineMetadata(INJECT_METADATA, existing, target);\n\n if (resourceName) {\n const resources: string[] = Reflect.getOwnMetadata(USE_RESOURCE_METADATA, target) ?? [];\n if (!resources.includes(resourceName)) {\n Reflect.defineMetadata(USE_RESOURCE_METADATA, [...resources, resourceName], target);\n }\n }\n };\n}\n","import type { ServiceContainer } from \"@celerity-sdk/types\";\nimport type { Datastore } from \"./types\";\nimport { datastoreToken, DEFAULT_DATASTORE_TOKEN } from \"./decorators\";\n\n/**\n * Resolves a {@link Datastore} instance from the DI container.\n * For function-based handlers where parameter decorators aren't available.\n *\n * @param container - The service container (typically `context.container`).\n * @param resourceName - The blueprint resource name. Omit when exactly one\n * datastore resource exists to use the default.\n *\n * @example\n * ```ts\n * const handler = createHttpHandler(async (req, ctx) => {\n * const users = await getDatastore(ctx.container, \"usersTable\");\n * const user = await users.getItem({ pk: req.pathParameters.userId });\n * });\n * ```\n */\nexport function getDatastore(\n container: ServiceContainer,\n resourceName?: string,\n): Promise<Datastore> {\n const token = resourceName ? datastoreToken(resourceName) : DEFAULT_DATASTORE_TOKEN;\n return container.resolve<Datastore>(token);\n}\n","import createDebug from \"debug\";\nimport type { CelerityLayer, BaseHandlerContext, CelerityTracer } from \"@celerity-sdk/types\";\nimport { TRACER_TOKEN, CONFIG_SERVICE_TOKEN } from \"@celerity-sdk/common\";\nimport {\n type ConfigService,\n captureResourceLinks,\n getLinksOfType,\n RESOURCE_CONFIG_NAMESPACE,\n} from \"@celerity-sdk/config\";\nimport { createDatastoreClient } from \"./factory\";\nimport { datastoreToken, DEFAULT_DATASTORE_TOKEN } from \"./decorators\";\n\nconst debug = createDebug(\"celerity:datastore\");\n\n/**\n * System layer that auto-registers {@link DatastoreClient} and per-resource\n * {@link Datastore} handles in the DI container.\n *\n * Reads resource link topology from `CELERITY_RESOURCE_LINKS` and resolves\n * actual table/collection names from the ConfigService \"resources\" namespace.\n * Must run after ConfigLayer in the layer pipeline.\n */\ntype DatastoreLayerConfig = {\n deployTarget: string | undefined;\n};\n\nfunction captureDatastoreLayerConfig(): DatastoreLayerConfig {\n return {\n deployTarget: process.env.CELERITY_DEPLOY_TARGET,\n };\n}\n\nexport class DatastoreLayer implements CelerityLayer<BaseHandlerContext> {\n private initialized = false;\n private config: DatastoreLayerConfig | null = null;\n\n async handle(context: BaseHandlerContext, next: () => Promise<unknown>): Promise<unknown> {\n if (!this.initialized) {\n this.config = captureDatastoreLayerConfig();\n\n const tracer = context.container.has(TRACER_TOKEN)\n ? await context.container.resolve<CelerityTracer>(TRACER_TOKEN)\n : undefined;\n\n const client = await createDatastoreClient({\n tracer,\n deployTarget: this.config.deployTarget,\n });\n debug(\"registering DatastoreClient\");\n context.container.register(\"DatastoreClient\", { useValue: client });\n\n const links = captureResourceLinks();\n const datastoreLinks = getLinksOfType(links, \"datastore\");\n\n if (datastoreLinks.size > 0) {\n const configService = await context.container.resolve<ConfigService>(CONFIG_SERVICE_TOKEN);\n const resourceConfig = configService.namespace(RESOURCE_CONFIG_NAMESPACE);\n\n for (const [resourceName, configKey] of datastoreLinks) {\n const actualName = await resourceConfig.getOrThrow(configKey);\n debug(\"registered datastore resource %s → %s\", resourceName, actualName);\n context.container.register(datastoreToken(resourceName), {\n useValue: client.datastore(actualName),\n });\n }\n\n if (datastoreLinks.size === 1) {\n const [, configKey] = [...datastoreLinks.entries()][0];\n const actualName = await resourceConfig.getOrThrow(configKey);\n debug(\"registered default datastore → %s\", actualName);\n context.container.register(DEFAULT_DATASTORE_TOKEN, {\n useValue: client.datastore(actualName),\n });\n }\n }\n\n this.initialized = true;\n }\n\n return next();\n }\n}\n"],"mappings":"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","names":["DatastoreClient","Symbol","for","resolveConfig","createDatastoreClient","options","resolved","resolveConfig","provider","DynamoDBDatastoreClient","aws","tracer","createLocalClient","Error","deployTarget","toLowerCase","undefined","captureDynamoDBConfig","localConfig","INJECT_METADATA","USE_RESOURCE_METADATA","datastoreToken","resourceName","Symbol","for","DEFAULT_DATASTORE_TOKEN","Datastore","target","_propertyKey","parameterIndex","token","existing","Reflect","getOwnMetadata","INJECT_METADATA","Map","set","defineMetadata","resources","USE_RESOURCE_METADATA","includes","getDatastore","container","resourceName","token","datastoreToken","DEFAULT_DATASTORE_TOKEN","resolve","createDebug","TRACER_TOKEN","CONFIG_SERVICE_TOKEN","captureResourceLinks","getLinksOfType","RESOURCE_CONFIG_NAMESPACE","debug","createDebug","captureDatastoreLayerConfig","deployTarget","process","env","CELERITY_DEPLOY_TARGET","DatastoreLayer","initialized","config","handle","context","next","tracer","container","has","TRACER_TOKEN","resolve","undefined","client","createDatastoreClient","register","useValue","links","captureResourceLinks","datastoreLinks","getLinksOfType","size","configService","CONFIG_SERVICE_TOKEN","resourceConfig","namespace","RESOURCE_CONFIG_NAMESPACE","resourceName","configKey","actualName","getOrThrow","datastoreToken","datastore","entries","DEFAULT_DATASTORE_TOKEN"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celerity-sdk/datastore",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "NoSQL data store abstraction for the Celerity Node SDK (DynamoDB / Cloud Firestore / Cosmos DB)",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -28,13 +28,13 @@
28
28
  "dist"
29
29
  ],
30
30
  "engines": {
31
- "node": ">=22.0.0"
31
+ "node": ">=24.0.0"
32
32
  },
33
33
  "dependencies": {
34
34
  "debug": "^4.4.0",
35
- "@celerity-sdk/types": "^0.6.0",
36
- "@celerity-sdk/config": "^0.6.0",
37
- "@celerity-sdk/common": "^0.6.0"
35
+ "@celerity-sdk/common": "^0.8.0",
36
+ "@celerity-sdk/types": "^0.8.0",
37
+ "@celerity-sdk/config": "^0.8.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@aws-sdk/client-dynamodb": "^3.750.0",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/providers/dynamodb/dynamodb-datastore-client.ts","../src/providers/dynamodb/dynamodb-datastore.ts","../src/providers/dynamodb/dynamodb-item-listing.ts","../src/providers/dynamodb/expressions.ts","../src/providers/dynamodb/errors.ts"],"sourcesContent":["import { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";\nimport { DynamoDBDocumentClient } from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { DatastoreClient, Datastore } from \"../../types\";\nimport { DynamoDBDatastore } from \"./dynamodb-datastore\";\nimport type { DynamoDBDatastoreConfig } from \"./types\";\nimport { captureDynamoDBConfig } from \"./config\";\n\nexport class DynamoDBDatastoreClient implements DatastoreClient {\n private client: DynamoDBClient | null = null;\n private docClient: DynamoDBDocumentClient | null = null;\n private readonly config: DynamoDBDatastoreConfig;\n\n constructor(\n config?: DynamoDBDatastoreConfig,\n private readonly tracer?: CelerityTracer,\n ) {\n this.config = config ?? captureDynamoDBConfig();\n }\n\n datastore(name: string): Datastore {\n return new DynamoDBDatastore(name, this.getDocClient(), this.tracer);\n }\n\n close(): void {\n this.docClient?.destroy();\n this.client?.destroy();\n this.docClient = null;\n this.client = null;\n }\n\n private getDocClient(): DynamoDBDocumentClient {\n if (!this.docClient) {\n this.client = new DynamoDBClient({\n region: this.config.region,\n endpoint: this.config.endpoint,\n credentials: this.config.credentials,\n });\n this.docClient = DynamoDBDocumentClient.from(this.client, {\n marshallOptions: { removeUndefinedValues: true },\n });\n }\n return this.docClient;\n }\n}\n","import createDebug from \"debug\";\nimport {\n GetCommand,\n PutCommand,\n DeleteCommand,\n BatchGetCommand,\n BatchWriteCommand,\n type DynamoDBDocumentClient,\n} from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer, CeleritySpan } from \"@celerity-sdk/types\";\nimport type {\n Datastore,\n ItemKey,\n GetItemOptions,\n PutItemOptions,\n DeleteItemOptions,\n QueryOptions,\n ScanOptions,\n ItemListing,\n BatchGetItemsOptions,\n BatchGetResult,\n BatchWriteOperation,\n BatchWriteResult,\n} from \"../../types\";\nimport { DatastoreError, ConditionalCheckFailedError } from \"../../errors\";\nimport { DynamoDBItemListing } from \"./dynamodb-item-listing\";\nimport { buildFilterExpression } from \"./expressions\";\nimport { isConditionalCheckFailedError } from \"./errors\";\n\nconst debug = createDebug(\"celerity:datastore:dynamodb\");\n\nexport class DynamoDBDatastore implements Datastore {\n constructor(\n private readonly tableName: string,\n private readonly client: DynamoDBDocumentClient,\n private readonly tracer?: CelerityTracer,\n ) {}\n\n async getItem<T = Record<string, unknown>>(\n key: ItemKey,\n options?: GetItemOptions,\n ): Promise<T | null> {\n debug(\"getItem %s %o\", this.tableName, key);\n return this.traced(\n \"celerity.datastore.get_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const response = await this.client.send(\n new GetCommand({\n TableName: this.tableName,\n Key: key,\n ConsistentRead: options?.consistentRead,\n }),\n );\n return (response.Item as T) ?? null;\n } catch (error) {\n throw new DatastoreError(\n `Failed to get item from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async putItem(item: Record<string, unknown>, options?: PutItemOptions): Promise<void> {\n debug(\"putItem %s\", this.tableName);\n return this.traced(\n \"celerity.datastore.put_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const conditionParams = options?.condition\n ? buildFilterExpression(options.condition)\n : undefined;\n\n await this.client.send(\n new PutCommand({\n TableName: this.tableName,\n Item: item,\n ConditionExpression: conditionParams?.expression,\n ExpressionAttributeNames: conditionParams?.names,\n ExpressionAttributeValues: conditionParams?.values,\n }),\n );\n } catch (error) {\n if (isConditionalCheckFailedError(error)) {\n throw new ConditionalCheckFailedError(this.tableName, { cause: error });\n }\n throw new DatastoreError(\n `Failed to put item in table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async deleteItem(key: ItemKey, options?: DeleteItemOptions): Promise<void> {\n debug(\"deleteItem %s %o\", this.tableName, key);\n return this.traced(\n \"celerity.datastore.delete_item\",\n { \"datastore.table\": this.tableName },\n async () => {\n try {\n const conditionParams = options?.condition\n ? buildFilterExpression(options.condition)\n : undefined;\n\n await this.client.send(\n new DeleteCommand({\n TableName: this.tableName,\n Key: key,\n ConditionExpression: conditionParams?.expression,\n ExpressionAttributeNames: conditionParams?.names,\n ExpressionAttributeValues: conditionParams?.values,\n }),\n );\n } catch (error) {\n if (isConditionalCheckFailedError(error)) {\n throw new ConditionalCheckFailedError(this.tableName, { cause: error });\n }\n throw new DatastoreError(\n `Failed to delete item from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n query<T = Record<string, unknown>>(options: QueryOptions): ItemListing<T> {\n debug(\"query %s pk=%s\", this.tableName, options.key.name);\n return new DynamoDBItemListing<T>(this.client, this.tableName, \"query\", options, this.tracer);\n }\n\n scan<T = Record<string, unknown>>(options?: ScanOptions): ItemListing<T> {\n debug(\"scan %s\", this.tableName);\n return new DynamoDBItemListing<T>(\n this.client,\n this.tableName,\n \"scan\",\n options ?? {},\n this.tracer,\n );\n }\n\n async batchGetItems<T = Record<string, unknown>>(\n keys: ItemKey[],\n options?: BatchGetItemsOptions,\n ): Promise<BatchGetResult<T>> {\n debug(\"batchGetItems %s count=%d\", this.tableName, keys.length);\n return this.traced(\n \"celerity.datastore.batch_get_items\",\n { \"datastore.table\": this.tableName, \"datastore.batch_size\": keys.length },\n async () => {\n try {\n const response = await this.client.send(\n new BatchGetCommand({\n RequestItems: {\n [this.tableName]: {\n Keys: keys,\n ConsistentRead: options?.consistentRead,\n },\n },\n }),\n );\n\n const items = (response.Responses?.[this.tableName] ?? []) as T[];\n const unprocessedKeys = (response.UnprocessedKeys?.[this.tableName]?.Keys ??\n []) as ItemKey[];\n\n return { items, unprocessedKeys };\n } catch (error) {\n throw new DatastoreError(\n `Failed to batch get items from table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n async batchWriteItems(operations: BatchWriteOperation[]): Promise<BatchWriteResult> {\n debug(\"batchWriteItems %s count=%d\", this.tableName, operations.length);\n return this.traced(\n \"celerity.datastore.batch_write_items\",\n { \"datastore.table\": this.tableName, \"datastore.batch_size\": operations.length },\n async () => {\n try {\n const writeRequests = operations.map((op) => {\n if (op.type === \"put\") {\n return { PutRequest: { Item: op.item } };\n }\n return { DeleteRequest: { Key: op.key } };\n });\n\n const response = await this.client.send(\n new BatchWriteCommand({\n RequestItems: { [this.tableName]: writeRequests },\n }),\n );\n\n const unprocessedRequests = response.UnprocessedItems?.[this.tableName] ?? [];\n const unprocessedOperations: BatchWriteOperation[] = unprocessedRequests.map((req) => {\n if (req.PutRequest) {\n return { type: \"put\" as const, item: req.PutRequest.Item! };\n }\n return { type: \"delete\" as const, key: req.DeleteRequest!.Key! as ItemKey };\n });\n\n return { unprocessedOperations };\n } catch (error) {\n throw new DatastoreError(\n `Failed to batch write items to table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n },\n );\n }\n\n private traced<T>(\n name: string,\n attributes: Record<string, string | number | boolean>,\n fn: (span?: CeleritySpan) => Promise<T>,\n ): Promise<T> {\n if (!this.tracer) return fn();\n return this.tracer.withSpan(name, (span) => fn(span), attributes);\n }\n}\n","import createDebug from \"debug\";\nimport { QueryCommand, ScanCommand, type DynamoDBDocumentClient } from \"@aws-sdk/lib-dynamodb\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { ItemListing, QueryOptions, ScanOptions } from \"../../types\";\nimport { DatastoreError } from \"../../errors\";\nimport { buildKeyConditionExpression, buildFilterExpression } from \"./expressions\";\n\nconst debug = createDebug(\"celerity:datastore:dynamodb\");\n\ntype CursorState = {\n lastEvaluatedKey: Record<string, unknown>;\n};\n\nfunction encodeCursor(lastEvaluatedKey: Record<string, unknown>): string {\n const state: CursorState = { lastEvaluatedKey };\n return Buffer.from(JSON.stringify(state)).toString(\"base64url\");\n}\n\nfunction decodeCursor(cursor: string): CursorState {\n return JSON.parse(Buffer.from(cursor, \"base64url\").toString(\"utf-8\")) as CursorState;\n}\n\nexport class DynamoDBItemListing<T> implements ItemListing<T> {\n private _cursor: string | undefined;\n\n constructor(\n private readonly client: DynamoDBDocumentClient,\n private readonly tableName: string,\n private readonly mode: \"query\" | \"scan\",\n private readonly options: QueryOptions | ScanOptions,\n private readonly tracer?: CelerityTracer,\n ) {\n this._cursor = options.cursor;\n }\n\n get cursor(): string | undefined {\n return this._cursor;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n const cursorState = this._cursor ? decodeCursor(this._cursor) : undefined;\n let exclusiveStartKey: Record<string, unknown> | undefined = cursorState?.lastEvaluatedKey;\n\n do {\n debug(\"%s page %s key=%o\", this.mode, this.tableName, exclusiveStartKey ?? \"(start)\");\n\n const response = await this.fetchPage(exclusiveStartKey);\n\n for (const item of response.Items ?? []) {\n yield item as T;\n }\n\n exclusiveStartKey = response.LastEvaluatedKey as Record<string, unknown> | undefined;\n\n if (exclusiveStartKey) {\n this._cursor = encodeCursor(exclusiveStartKey);\n } else {\n this._cursor = undefined;\n }\n } while (exclusiveStartKey);\n }\n\n private async fetchPage(exclusiveStartKey?: Record<string, unknown>) {\n const command =\n this.mode === \"query\"\n ? this.buildQueryCommand(exclusiveStartKey)\n : this.buildScanCommand(exclusiveStartKey);\n\n const doFetch = async () => {\n try {\n return await this.client.send(command);\n } catch (error) {\n throw new DatastoreError(\n `Failed to ${this.mode} table \"${this.tableName}\"`,\n this.tableName,\n { cause: error },\n );\n }\n };\n\n if (!this.tracer) return doFetch();\n return this.tracer.withSpan(`celerity.datastore.${this.mode}_page`, () => doFetch(), {\n \"datastore.table\": this.tableName,\n });\n }\n\n private buildQueryCommand(exclusiveStartKey?: Record<string, unknown>) {\n const opts = this.options as QueryOptions;\n const keyExpr = buildKeyConditionExpression(opts.key, opts.range);\n\n const filterExpr = opts.filter ? buildFilterExpression(opts.filter) : undefined;\n\n return new QueryCommand({\n TableName: this.tableName,\n IndexName: opts.indexName,\n KeyConditionExpression: keyExpr.expression,\n FilterExpression: filterExpr?.expression,\n ExpressionAttributeNames: { ...keyExpr.names, ...filterExpr?.names },\n ExpressionAttributeValues: { ...keyExpr.values, ...filterExpr?.values },\n ScanIndexForward: opts.sortAscending,\n Limit: opts.maxResults,\n ExclusiveStartKey: exclusiveStartKey,\n ConsistentRead: opts.consistentRead,\n });\n }\n\n private buildScanCommand(exclusiveStartKey?: Record<string, unknown>) {\n const opts = this.options as ScanOptions;\n\n const filterExpr = opts.filter ? buildFilterExpression(opts.filter) : undefined;\n\n return new ScanCommand({\n TableName: this.tableName,\n IndexName: opts.indexName,\n FilterExpression: filterExpr?.expression,\n ExpressionAttributeNames:\n filterExpr?.names && Object.keys(filterExpr.names).length > 0\n ? filterExpr.names\n : undefined,\n ExpressionAttributeValues:\n filterExpr?.values && Object.keys(filterExpr.values).length > 0\n ? filterExpr.values\n : undefined,\n Limit: opts.maxResults,\n ExclusiveStartKey: exclusiveStartKey,\n ConsistentRead: opts.consistentRead,\n });\n }\n}\n","import type { KeyCondition, RangeCondition, ConditionExpression } from \"../../types\";\n\nexport type ExpressionResult = {\n expression: string;\n names: Record<string, string>;\n values: Record<string, unknown>;\n};\n\nconst COMPARISON_OPERATORS = {\n eq: \"=\",\n ne: \"<>\",\n lt: \"<\",\n le: \"<=\",\n gt: \">\",\n ge: \">=\",\n} as const;\n\n/**\n * Builds a DynamoDB KeyConditionExpression from a key condition and optional range condition.\n * Uses `#k`/`:k` prefixed placeholders to avoid collision with filter placeholders.\n */\nexport function buildKeyConditionExpression(\n key: KeyCondition,\n range?: RangeCondition,\n): ExpressionResult {\n const names: Record<string, string> = {};\n const values: Record<string, unknown> = {};\n let counter = 0;\n\n const pkName = `#k${counter}`;\n const pkValue = `:k${counter}`;\n names[pkName] = key.name;\n values[pkValue] = key.value;\n counter++;\n\n let expression = `${pkName} = ${pkValue}`;\n\n if (range) {\n const skName = `#k${counter}`;\n names[skName] = range.name;\n\n switch (range.operator) {\n case \"eq\":\n case \"lt\":\n case \"le\":\n case \"gt\":\n case \"ge\": {\n const skValue = `:k${counter}`;\n values[skValue] = range.value;\n expression += ` AND ${skName} ${COMPARISON_OPERATORS[range.operator]} ${skValue}`;\n break;\n }\n case \"between\": {\n const lowVal = `:k${counter}a`;\n const highVal = `:k${counter}b`;\n values[lowVal] = range.low;\n values[highVal] = range.high;\n expression += ` AND ${skName} BETWEEN ${lowVal} AND ${highVal}`;\n break;\n }\n case \"startsWith\": {\n const skValue = `:k${counter}`;\n values[skValue] = range.value;\n expression += ` AND begins_with(${skName}, ${skValue})`;\n break;\n }\n }\n }\n\n return { expression, names, values };\n}\n\n/**\n * Builds a DynamoDB FilterExpression (or ConditionExpression for writes)\n * from one or more Condition objects. Conditions are AND'd together.\n * Uses `#f`/`:f` prefixed placeholders to avoid collision with key placeholders.\n */\nexport function buildFilterExpression(conditions: ConditionExpression): ExpressionResult {\n const condArray = Array.isArray(conditions) ? conditions : [conditions];\n const names: Record<string, string> = {};\n const values: Record<string, unknown> = {};\n const parts: string[] = [];\n let counter = 0;\n\n for (const cond of condArray) {\n const attrName = `#f${counter}`;\n names[attrName] = cond.name;\n\n switch (cond.operator) {\n case \"eq\":\n case \"ne\":\n case \"lt\":\n case \"le\":\n case \"gt\":\n case \"ge\": {\n const valKey = `:f${counter}`;\n values[valKey] = cond.value;\n parts.push(`${attrName} ${COMPARISON_OPERATORS[cond.operator]} ${valKey}`);\n break;\n }\n case \"between\": {\n const lowVal = `:f${counter}a`;\n const highVal = `:f${counter}b`;\n values[lowVal] = cond.low;\n values[highVal] = cond.high;\n parts.push(`${attrName} BETWEEN ${lowVal} AND ${highVal}`);\n break;\n }\n case \"startsWith\":\n case \"contains\": {\n const valKey = `:f${counter}`;\n values[valKey] = cond.value;\n const fnName = cond.operator === \"startsWith\" ? \"begins_with\" : \"contains\";\n parts.push(`${fnName}(${attrName}, ${valKey})`);\n break;\n }\n case \"exists\":\n parts.push(`attribute_exists(${attrName})`);\n break;\n }\n\n counter++;\n }\n\n return { expression: parts.join(\" AND \"), names, values };\n}\n","/**\n * Checks if an error is a DynamoDB ConditionalCheckFailedException.\n */\nexport function isConditionalCheckFailedError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n return (error as { name?: string }).name === \"ConditionalCheckFailedException\";\n}\n"],"mappings":"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","names":["DynamoDBClient","DynamoDBDocumentClient","createDebug","GetCommand","PutCommand","DeleteCommand","BatchGetCommand","BatchWriteCommand","createDebug","QueryCommand","ScanCommand","COMPARISON_OPERATORS","eq","ne","lt","le","gt","ge","buildKeyConditionExpression","key","range","names","values","counter","pkName","pkValue","name","value","expression","skName","operator","skValue","lowVal","highVal","low","high","buildFilterExpression","conditions","condArray","Array","isArray","parts","cond","attrName","valKey","push","fnName","join","debug","createDebug","encodeCursor","lastEvaluatedKey","state","Buffer","from","JSON","stringify","toString","decodeCursor","cursor","parse","DynamoDBItemListing","_cursor","client","tableName","mode","options","tracer","Symbol","asyncIterator","cursorState","undefined","exclusiveStartKey","response","fetchPage","item","Items","LastEvaluatedKey","command","buildQueryCommand","buildScanCommand","doFetch","send","error","DatastoreError","cause","withSpan","opts","keyExpr","buildKeyConditionExpression","key","range","filterExpr","filter","buildFilterExpression","QueryCommand","TableName","IndexName","indexName","KeyConditionExpression","expression","FilterExpression","ExpressionAttributeNames","names","ExpressionAttributeValues","values","ScanIndexForward","sortAscending","Limit","maxResults","ExclusiveStartKey","ConsistentRead","consistentRead","ScanCommand","Object","keys","length","isConditionalCheckFailedError","error","Error","name","debug","createDebug","DynamoDBDatastore","tableName","client","tracer","getItem","key","options","traced","response","send","GetCommand","TableName","Key","ConsistentRead","consistentRead","Item","error","DatastoreError","cause","putItem","item","conditionParams","condition","buildFilterExpression","undefined","PutCommand","ConditionExpression","expression","ExpressionAttributeNames","names","ExpressionAttributeValues","values","isConditionalCheckFailedError","ConditionalCheckFailedError","deleteItem","DeleteCommand","query","name","DynamoDBItemListing","scan","batchGetItems","keys","length","BatchGetCommand","RequestItems","Keys","items","Responses","unprocessedKeys","UnprocessedKeys","batchWriteItems","operations","writeRequests","map","op","type","PutRequest","DeleteRequest","BatchWriteCommand","unprocessedRequests","UnprocessedItems","unprocessedOperations","req","attributes","fn","withSpan","span","DynamoDBDatastoreClient","client","docClient","config","tracer","captureDynamoDBConfig","datastore","name","DynamoDBDatastore","getDocClient","close","destroy","DynamoDBClient","region","endpoint","credentials","DynamoDBDocumentClient","from","marshallOptions","removeUndefinedValues"]}