@tslock/dynamodb 1.0.2 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,6 +48,18 @@ await executor.executeWithLock(
48
48
  | `partitionKey` | `'_id'` | The partition key attribute name. |
49
49
  | `sortKey` | `undefined` | `{ name, value }` if your table uses a composite key. |
50
50
 
51
+ ## Integration tests
52
+
53
+ The shared extensible-lock and fuzz contracts run against an ephemeral DynamoDB Local container:
54
+
55
+ ```bash
56
+ pnpm --filter @tslock/dynamodb test:integration
57
+ ```
58
+
59
+ Docker is required for this suite.
60
+
61
+ > **Lock-name safety:** Lock names must be non-empty, contain no control characters, and be at most 1024 UTF-8 bytes. If a composite key is used, the configured sort-key value is shared across all lock names.
62
+
51
63
  ## Requirements
52
64
 
53
65
  - Node.js >= 22
package/dist/index.cjs CHANGED
@@ -124,7 +124,10 @@ var DynamoDBAccessor = class {
124
124
  TableName: this.tableName,
125
125
  Key: this.buildKey(config.name),
126
126
  UpdateExpression: "SET lockUntil = :unlockTime",
127
- ConditionExpression: `attribute_exists(${this.partitionKey})`,
127
+ ConditionExpression: "attribute_exists(#partitionKey)",
128
+ ExpressionAttributeNames: {
129
+ "#partitionKey": this.partitionKey
130
+ },
128
131
  ExpressionAttributeValues: {
129
132
  ":unlockTime": { S: isoUnlock }
130
133
  }
@@ -138,8 +141,9 @@ var DynamoDBAccessor = class {
138
141
  };
139
142
 
140
143
  // src/dynamodb-lock-provider-options.ts
144
+ var import_core3 = require("@tslock/core");
141
145
  function validateOptions(options) {
142
- if (!options.tableName) throw new Error("tableName is required");
146
+ if (!options.tableName) throw new import_core3.LockException("DynamoDBConfiguration: tableName is required");
143
147
  return {
144
148
  tableName: options.tableName,
145
149
  partitionKey: options.partitionKey ?? "_id",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/dynamodb-lock-provider.ts","../src/dynamodb-accessor.ts","../src/dynamodb-lock.ts","../src/dynamodb-lock-provider-options.ts"],"sourcesContent":["export { DynamoDBLockProvider } from './dynamodb-lock-provider.js';\nexport type { DynamoDBLockProviderOptions } from './dynamodb-lock-provider-options.js';\n","import { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport type { ExtensibleLockProvider, LockConfiguration, SimpleLock } from '@tslock/core';\nimport { DynamoDBAccessor } from './dynamodb-accessor.js';\nimport { type DynamoDBLockProviderOptions, validateOptions } from './dynamodb-lock-provider-options.js';\n\nexport class DynamoDBLockProvider implements ExtensibleLockProvider {\n private readonly accessor: DynamoDBAccessor;\n\n constructor(options: DynamoDBLockProviderOptions) {\n const opts = validateOptions(options);\n this.accessor = new DynamoDBAccessor(\n options.client ?? new DynamoDBClient({}),\n opts.tableName,\n opts.partitionKey,\n opts.sortKey,\n );\n }\n\n async lock(config: LockConfiguration): Promise<SimpleLock | undefined> {\n return this.accessor.lock(config);\n }\n}\n","import type { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport { ConditionalCheckFailedException, UpdateItemCommand } from '@aws-sdk/client-dynamodb';\nimport { ClockProvider, type LockConfiguration, Utils, lockAtMostUntil, unlockTime } from '@tslock/core';\nimport { DynamoDBLock } from './dynamodb-lock.js';\n\nexport class DynamoDBAccessor {\n constructor(\n private readonly client: DynamoDBClient,\n private readonly tableName: string,\n private readonly partitionKey: string,\n private readonly sortKey?: { name: string; value: string },\n ) {}\n\n private buildKey(name: string): Record<string, { S: string }> {\n const key: Record<string, { S: string }> = { [this.partitionKey]: { S: name } };\n if (this.sortKey) {\n key[this.sortKey.name] = { S: this.sortKey.value };\n }\n return key;\n }\n\n async lock(config: LockConfiguration): Promise<DynamoDBLock | undefined> {\n const now = ClockProvider.now();\n const isoNow = Utils.toIsoString(now);\n const isoLockAtMostUntil = Utils.toIsoString(lockAtMostUntil(config));\n const hostname = Utils.getHostname();\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :lockUntil, lockedAt = :lockedAt, lockedBy = :lockedBy',\n ConditionExpression: 'lockUntil <= :lockedAt OR attribute_not_exists(lockUntil)',\n ExpressionAttributeValues: {\n ':lockUntil': { S: isoLockAtMostUntil },\n ':lockedAt': { S: isoNow },\n ':lockedBy': { S: hostname },\n },\n }),\n );\n return new DynamoDBLock(config, this);\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return undefined;\n throw e;\n }\n }\n\n async extend(config: LockConfiguration): Promise<DynamoDBLock | undefined> {\n const now = ClockProvider.now();\n const isoNow = Utils.toIsoString(now);\n const isoNewLockAtMostUntil = Utils.toIsoString(lockAtMostUntil(config));\n const hostname = Utils.getHostname();\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :lockUntil',\n ConditionExpression: 'lockedBy = :lockedBy AND lockUntil > :now',\n ExpressionAttributeValues: {\n ':lockUntil': { S: isoNewLockAtMostUntil },\n ':lockedBy': { S: hostname },\n ':now': { S: isoNow },\n },\n }),\n );\n return new DynamoDBLock(config, this);\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return undefined;\n throw e;\n }\n }\n\n async unlock(config: LockConfiguration): Promise<void> {\n const isoUnlock = Utils.toIsoString(unlockTime(config));\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :unlockTime',\n ConditionExpression: `attribute_exists(${this.partitionKey})`,\n ExpressionAttributeValues: {\n ':unlockTime': { S: isoUnlock },\n },\n }),\n );\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return;\n throw e;\n }\n }\n}\n","import { AbstractSimpleLock, type LockConfiguration, type SimpleLock } from '@tslock/core';\nimport type { DynamoDBAccessor } from './dynamodb-accessor.js';\n\nexport class DynamoDBLock extends AbstractSimpleLock {\n constructor(\n config: LockConfiguration,\n private readonly accessor: DynamoDBAccessor,\n ) {\n super(config);\n }\n\n protected override async doUnlock(): Promise<void> {\n await this.accessor.unlock(this.config);\n }\n\n protected override async doExtend(newConfig: LockConfiguration): Promise<SimpleLock | undefined> {\n return await this.accessor.extend(newConfig);\n }\n}\n","import type { DynamoDBClient } from '@aws-sdk/client-dynamodb';\n\nexport interface DynamoDBLockProviderOptions {\n client?: DynamoDBClient;\n tableName: string;\n partitionKey?: string;\n sortKey?: { name: string; value: string };\n}\n\nexport interface ResolvedOptions {\n tableName: string;\n partitionKey: string;\n sortKey?: { name: string; value: string };\n}\n\nexport function validateOptions(options: DynamoDBLockProviderOptions): ResolvedOptions {\n if (!options.tableName) throw new Error('tableName is required');\n return {\n tableName: options.tableName,\n partitionKey: options.partitionKey ?? '_id',\n sortKey: options.sortKey,\n };\n}\n"],"mappings":"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","names":["import_client_dynamodb","import_core"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/dynamodb-lock-provider.ts","../src/dynamodb-accessor.ts","../src/dynamodb-lock.ts","../src/dynamodb-lock-provider-options.ts"],"sourcesContent":["export { DynamoDBLockProvider } from './dynamodb-lock-provider.js';\nexport type { DynamoDBLockProviderOptions } from './dynamodb-lock-provider-options.js';\n","import { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport type { ExtensibleLockProvider, LockConfiguration, SimpleLock } from '@tslock/core';\nimport { DynamoDBAccessor } from './dynamodb-accessor.js';\nimport { type DynamoDBLockProviderOptions, validateOptions } from './dynamodb-lock-provider-options.js';\n\nexport class DynamoDBLockProvider implements ExtensibleLockProvider {\n private readonly accessor: DynamoDBAccessor;\n\n constructor(options: DynamoDBLockProviderOptions) {\n const opts = validateOptions(options);\n this.accessor = new DynamoDBAccessor(\n options.client ?? new DynamoDBClient({}),\n opts.tableName,\n opts.partitionKey,\n opts.sortKey,\n );\n }\n\n async lock(config: LockConfiguration): Promise<SimpleLock | undefined> {\n return this.accessor.lock(config);\n }\n}\n","import type { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport { ConditionalCheckFailedException, UpdateItemCommand } from '@aws-sdk/client-dynamodb';\nimport { ClockProvider, type LockConfiguration, Utils, lockAtMostUntil, unlockTime } from '@tslock/core';\nimport { DynamoDBLock } from './dynamodb-lock.js';\n\nexport class DynamoDBAccessor {\n constructor(\n private readonly client: DynamoDBClient,\n private readonly tableName: string,\n private readonly partitionKey: string,\n private readonly sortKey?: { name: string; value: string },\n ) {}\n\n private buildKey(name: string): Record<string, { S: string }> {\n const key: Record<string, { S: string }> = { [this.partitionKey]: { S: name } };\n if (this.sortKey) {\n key[this.sortKey.name] = { S: this.sortKey.value };\n }\n return key;\n }\n\n async lock(config: LockConfiguration): Promise<DynamoDBLock | undefined> {\n const now = ClockProvider.now();\n const isoNow = Utils.toIsoString(now);\n const isoLockAtMostUntil = Utils.toIsoString(lockAtMostUntil(config));\n const hostname = Utils.getHostname();\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :lockUntil, lockedAt = :lockedAt, lockedBy = :lockedBy',\n ConditionExpression: 'lockUntil <= :lockedAt OR attribute_not_exists(lockUntil)',\n ExpressionAttributeValues: {\n ':lockUntil': { S: isoLockAtMostUntil },\n ':lockedAt': { S: isoNow },\n ':lockedBy': { S: hostname },\n },\n }),\n );\n return new DynamoDBLock(config, this);\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return undefined;\n throw e;\n }\n }\n\n async extend(config: LockConfiguration): Promise<DynamoDBLock | undefined> {\n const now = ClockProvider.now();\n const isoNow = Utils.toIsoString(now);\n const isoNewLockAtMostUntil = Utils.toIsoString(lockAtMostUntil(config));\n const hostname = Utils.getHostname();\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :lockUntil',\n ConditionExpression: 'lockedBy = :lockedBy AND lockUntil > :now',\n ExpressionAttributeValues: {\n ':lockUntil': { S: isoNewLockAtMostUntil },\n ':lockedBy': { S: hostname },\n ':now': { S: isoNow },\n },\n }),\n );\n return new DynamoDBLock(config, this);\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return undefined;\n throw e;\n }\n }\n\n async unlock(config: LockConfiguration): Promise<void> {\n const isoUnlock = Utils.toIsoString(unlockTime(config));\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :unlockTime',\n ConditionExpression: 'attribute_exists(#partitionKey)',\n ExpressionAttributeNames: {\n '#partitionKey': this.partitionKey,\n },\n ExpressionAttributeValues: {\n ':unlockTime': { S: isoUnlock },\n },\n }),\n );\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return;\n throw e;\n }\n }\n}\n","import { AbstractSimpleLock, type LockConfiguration, type SimpleLock } from '@tslock/core';\nimport type { DynamoDBAccessor } from './dynamodb-accessor.js';\n\nexport class DynamoDBLock extends AbstractSimpleLock {\n constructor(\n config: LockConfiguration,\n private readonly accessor: DynamoDBAccessor,\n ) {\n super(config);\n }\n\n protected override async doUnlock(): Promise<void> {\n await this.accessor.unlock(this.config);\n }\n\n protected override async doExtend(newConfig: LockConfiguration): Promise<SimpleLock | undefined> {\n return await this.accessor.extend(newConfig);\n }\n}\n","import type { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport { LockException } from '@tslock/core';\n\nexport interface DynamoDBLockProviderOptions {\n client?: DynamoDBClient;\n tableName: string;\n partitionKey?: string;\n sortKey?: { name: string; value: string };\n}\n\nexport interface ResolvedOptions {\n tableName: string;\n partitionKey: string;\n sortKey?: { name: string; value: string };\n}\n\nexport function validateOptions(options: DynamoDBLockProviderOptions): ResolvedOptions {\n if (!options.tableName) throw new LockException('DynamoDBConfiguration: tableName is required');\n return {\n tableName: options.tableName,\n partitionKey: options.partitionKey ?? '_id',\n sortKey: options.sortKey,\n };\n}\n"],"mappings":"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","names":["import_client_dynamodb","import_core","import_core"]}
package/dist/index.js CHANGED
@@ -98,7 +98,10 @@ var DynamoDBAccessor = class {
98
98
  TableName: this.tableName,
99
99
  Key: this.buildKey(config.name),
100
100
  UpdateExpression: "SET lockUntil = :unlockTime",
101
- ConditionExpression: `attribute_exists(${this.partitionKey})`,
101
+ ConditionExpression: "attribute_exists(#partitionKey)",
102
+ ExpressionAttributeNames: {
103
+ "#partitionKey": this.partitionKey
104
+ },
102
105
  ExpressionAttributeValues: {
103
106
  ":unlockTime": { S: isoUnlock }
104
107
  }
@@ -112,8 +115,9 @@ var DynamoDBAccessor = class {
112
115
  };
113
116
 
114
117
  // src/dynamodb-lock-provider-options.ts
118
+ import { LockException } from "@tslock/core";
115
119
  function validateOptions(options) {
116
- if (!options.tableName) throw new Error("tableName is required");
120
+ if (!options.tableName) throw new LockException("DynamoDBConfiguration: tableName is required");
117
121
  return {
118
122
  tableName: options.tableName,
119
123
  partitionKey: options.partitionKey ?? "_id",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dynamodb-lock-provider.ts","../src/dynamodb-accessor.ts","../src/dynamodb-lock.ts","../src/dynamodb-lock-provider-options.ts"],"sourcesContent":["import { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport type { ExtensibleLockProvider, LockConfiguration, SimpleLock } from '@tslock/core';\nimport { DynamoDBAccessor } from './dynamodb-accessor.js';\nimport { type DynamoDBLockProviderOptions, validateOptions } from './dynamodb-lock-provider-options.js';\n\nexport class DynamoDBLockProvider implements ExtensibleLockProvider {\n private readonly accessor: DynamoDBAccessor;\n\n constructor(options: DynamoDBLockProviderOptions) {\n const opts = validateOptions(options);\n this.accessor = new DynamoDBAccessor(\n options.client ?? new DynamoDBClient({}),\n opts.tableName,\n opts.partitionKey,\n opts.sortKey,\n );\n }\n\n async lock(config: LockConfiguration): Promise<SimpleLock | undefined> {\n return this.accessor.lock(config);\n }\n}\n","import type { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport { ConditionalCheckFailedException, UpdateItemCommand } from '@aws-sdk/client-dynamodb';\nimport { ClockProvider, type LockConfiguration, Utils, lockAtMostUntil, unlockTime } from '@tslock/core';\nimport { DynamoDBLock } from './dynamodb-lock.js';\n\nexport class DynamoDBAccessor {\n constructor(\n private readonly client: DynamoDBClient,\n private readonly tableName: string,\n private readonly partitionKey: string,\n private readonly sortKey?: { name: string; value: string },\n ) {}\n\n private buildKey(name: string): Record<string, { S: string }> {\n const key: Record<string, { S: string }> = { [this.partitionKey]: { S: name } };\n if (this.sortKey) {\n key[this.sortKey.name] = { S: this.sortKey.value };\n }\n return key;\n }\n\n async lock(config: LockConfiguration): Promise<DynamoDBLock | undefined> {\n const now = ClockProvider.now();\n const isoNow = Utils.toIsoString(now);\n const isoLockAtMostUntil = Utils.toIsoString(lockAtMostUntil(config));\n const hostname = Utils.getHostname();\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :lockUntil, lockedAt = :lockedAt, lockedBy = :lockedBy',\n ConditionExpression: 'lockUntil <= :lockedAt OR attribute_not_exists(lockUntil)',\n ExpressionAttributeValues: {\n ':lockUntil': { S: isoLockAtMostUntil },\n ':lockedAt': { S: isoNow },\n ':lockedBy': { S: hostname },\n },\n }),\n );\n return new DynamoDBLock(config, this);\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return undefined;\n throw e;\n }\n }\n\n async extend(config: LockConfiguration): Promise<DynamoDBLock | undefined> {\n const now = ClockProvider.now();\n const isoNow = Utils.toIsoString(now);\n const isoNewLockAtMostUntil = Utils.toIsoString(lockAtMostUntil(config));\n const hostname = Utils.getHostname();\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :lockUntil',\n ConditionExpression: 'lockedBy = :lockedBy AND lockUntil > :now',\n ExpressionAttributeValues: {\n ':lockUntil': { S: isoNewLockAtMostUntil },\n ':lockedBy': { S: hostname },\n ':now': { S: isoNow },\n },\n }),\n );\n return new DynamoDBLock(config, this);\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return undefined;\n throw e;\n }\n }\n\n async unlock(config: LockConfiguration): Promise<void> {\n const isoUnlock = Utils.toIsoString(unlockTime(config));\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :unlockTime',\n ConditionExpression: `attribute_exists(${this.partitionKey})`,\n ExpressionAttributeValues: {\n ':unlockTime': { S: isoUnlock },\n },\n }),\n );\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return;\n throw e;\n }\n }\n}\n","import { AbstractSimpleLock, type LockConfiguration, type SimpleLock } from '@tslock/core';\nimport type { DynamoDBAccessor } from './dynamodb-accessor.js';\n\nexport class DynamoDBLock extends AbstractSimpleLock {\n constructor(\n config: LockConfiguration,\n private readonly accessor: DynamoDBAccessor,\n ) {\n super(config);\n }\n\n protected override async doUnlock(): Promise<void> {\n await this.accessor.unlock(this.config);\n }\n\n protected override async doExtend(newConfig: LockConfiguration): Promise<SimpleLock | undefined> {\n return await this.accessor.extend(newConfig);\n }\n}\n","import type { DynamoDBClient } from '@aws-sdk/client-dynamodb';\n\nexport interface DynamoDBLockProviderOptions {\n client?: DynamoDBClient;\n tableName: string;\n partitionKey?: string;\n sortKey?: { name: string; value: string };\n}\n\nexport interface ResolvedOptions {\n tableName: string;\n partitionKey: string;\n sortKey?: { name: string; value: string };\n}\n\nexport function validateOptions(options: DynamoDBLockProviderOptions): ResolvedOptions {\n if (!options.tableName) throw new Error('tableName is required');\n return {\n tableName: options.tableName,\n partitionKey: options.partitionKey ?? '_id',\n sortKey: options.sortKey,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/dynamodb-lock-provider.ts","../src/dynamodb-accessor.ts","../src/dynamodb-lock.ts","../src/dynamodb-lock-provider-options.ts"],"sourcesContent":["import { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport type { ExtensibleLockProvider, LockConfiguration, SimpleLock } from '@tslock/core';\nimport { DynamoDBAccessor } from './dynamodb-accessor.js';\nimport { type DynamoDBLockProviderOptions, validateOptions } from './dynamodb-lock-provider-options.js';\n\nexport class DynamoDBLockProvider implements ExtensibleLockProvider {\n private readonly accessor: DynamoDBAccessor;\n\n constructor(options: DynamoDBLockProviderOptions) {\n const opts = validateOptions(options);\n this.accessor = new DynamoDBAccessor(\n options.client ?? new DynamoDBClient({}),\n opts.tableName,\n opts.partitionKey,\n opts.sortKey,\n );\n }\n\n async lock(config: LockConfiguration): Promise<SimpleLock | undefined> {\n return this.accessor.lock(config);\n }\n}\n","import type { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport { ConditionalCheckFailedException, UpdateItemCommand } from '@aws-sdk/client-dynamodb';\nimport { ClockProvider, type LockConfiguration, Utils, lockAtMostUntil, unlockTime } from '@tslock/core';\nimport { DynamoDBLock } from './dynamodb-lock.js';\n\nexport class DynamoDBAccessor {\n constructor(\n private readonly client: DynamoDBClient,\n private readonly tableName: string,\n private readonly partitionKey: string,\n private readonly sortKey?: { name: string; value: string },\n ) {}\n\n private buildKey(name: string): Record<string, { S: string }> {\n const key: Record<string, { S: string }> = { [this.partitionKey]: { S: name } };\n if (this.sortKey) {\n key[this.sortKey.name] = { S: this.sortKey.value };\n }\n return key;\n }\n\n async lock(config: LockConfiguration): Promise<DynamoDBLock | undefined> {\n const now = ClockProvider.now();\n const isoNow = Utils.toIsoString(now);\n const isoLockAtMostUntil = Utils.toIsoString(lockAtMostUntil(config));\n const hostname = Utils.getHostname();\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :lockUntil, lockedAt = :lockedAt, lockedBy = :lockedBy',\n ConditionExpression: 'lockUntil <= :lockedAt OR attribute_not_exists(lockUntil)',\n ExpressionAttributeValues: {\n ':lockUntil': { S: isoLockAtMostUntil },\n ':lockedAt': { S: isoNow },\n ':lockedBy': { S: hostname },\n },\n }),\n );\n return new DynamoDBLock(config, this);\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return undefined;\n throw e;\n }\n }\n\n async extend(config: LockConfiguration): Promise<DynamoDBLock | undefined> {\n const now = ClockProvider.now();\n const isoNow = Utils.toIsoString(now);\n const isoNewLockAtMostUntil = Utils.toIsoString(lockAtMostUntil(config));\n const hostname = Utils.getHostname();\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :lockUntil',\n ConditionExpression: 'lockedBy = :lockedBy AND lockUntil > :now',\n ExpressionAttributeValues: {\n ':lockUntil': { S: isoNewLockAtMostUntil },\n ':lockedBy': { S: hostname },\n ':now': { S: isoNow },\n },\n }),\n );\n return new DynamoDBLock(config, this);\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return undefined;\n throw e;\n }\n }\n\n async unlock(config: LockConfiguration): Promise<void> {\n const isoUnlock = Utils.toIsoString(unlockTime(config));\n\n try {\n await this.client.send(\n new UpdateItemCommand({\n TableName: this.tableName,\n Key: this.buildKey(config.name),\n UpdateExpression: 'SET lockUntil = :unlockTime',\n ConditionExpression: 'attribute_exists(#partitionKey)',\n ExpressionAttributeNames: {\n '#partitionKey': this.partitionKey,\n },\n ExpressionAttributeValues: {\n ':unlockTime': { S: isoUnlock },\n },\n }),\n );\n } catch (e) {\n if (e instanceof ConditionalCheckFailedException) return;\n throw e;\n }\n }\n}\n","import { AbstractSimpleLock, type LockConfiguration, type SimpleLock } from '@tslock/core';\nimport type { DynamoDBAccessor } from './dynamodb-accessor.js';\n\nexport class DynamoDBLock extends AbstractSimpleLock {\n constructor(\n config: LockConfiguration,\n private readonly accessor: DynamoDBAccessor,\n ) {\n super(config);\n }\n\n protected override async doUnlock(): Promise<void> {\n await this.accessor.unlock(this.config);\n }\n\n protected override async doExtend(newConfig: LockConfiguration): Promise<SimpleLock | undefined> {\n return await this.accessor.extend(newConfig);\n }\n}\n","import type { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport { LockException } from '@tslock/core';\n\nexport interface DynamoDBLockProviderOptions {\n client?: DynamoDBClient;\n tableName: string;\n partitionKey?: string;\n sortKey?: { name: string; value: string };\n}\n\nexport interface ResolvedOptions {\n tableName: string;\n partitionKey: string;\n sortKey?: { name: string; value: string };\n}\n\nexport function validateOptions(options: DynamoDBLockProviderOptions): ResolvedOptions {\n if (!options.tableName) throw new LockException('DynamoDBConfiguration: tableName is required');\n return {\n tableName: options.tableName,\n partitionKey: options.partitionKey ?? '_id',\n sortKey: options.sortKey,\n };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tslock/dynamodb",
3
- "version": "1.0.2",
3
+ "version": "2.0.1",
4
4
  "description": "TSLock provider for Amazon DynamoDB",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -12,7 +12,8 @@
12
12
  "types": "./dist/index.d.ts",
13
13
  "import": "./dist/index.js",
14
14
  "require": "./dist/index.cjs"
15
- }
15
+ },
16
+ "./package.json": "./package.json"
16
17
  },
17
18
  "files": [
18
19
  "dist"
@@ -22,7 +23,7 @@
22
23
  },
23
24
  "peerDependencies": {
24
25
  "@aws-sdk/client-dynamodb": "^3.0.0",
25
- "@tslock/core": "1.0.2"
26
+ "@tslock/core": "2.0.1"
26
27
  },
27
28
  "peerDependenciesMeta": {
28
29
  "@tslock/core": {
@@ -33,11 +34,13 @@
33
34
  }
34
35
  },
35
36
  "devDependencies": {
37
+ "testcontainers": "^12.0.4",
36
38
  "typescript": "^5.5.0",
37
39
  "tsup": "^8.0.0",
38
40
  "vitest": "^2.0.0",
39
41
  "@aws-sdk/client-dynamodb": "^3.0.0",
40
- "@tslock/core": "1.0.2"
42
+ "@tslock/core": "2.0.1",
43
+ "@tslock/test-support": "2.0.1"
41
44
  },
42
45
  "publishConfig": {
43
46
  "access": "public"
@@ -47,9 +50,11 @@
47
50
  "url": "git+https://github.com/drmaas/tslock.git",
48
51
  "directory": "packages/dynamodb"
49
52
  },
53
+ "sideEffects": false,
50
54
  "scripts": {
51
55
  "build": "tsup",
52
56
  "test": "vitest run",
57
+ "test:integration": "vitest run --config vitest.integration.config.ts",
53
58
  "test:watch": "vitest",
54
59
  "typecheck": "tsc --noEmit"
55
60
  }