@kensio/yulin 0.1.0 → 0.1.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.
Files changed (57) hide show
  1. package/dist/service/cloudfront/factory/cloudfront-functions.factory.d.ts +4 -4
  2. package/dist/service/cloudfront/factory/cloudfront-functions.factory.d.ts.map +1 -1
  3. package/dist/service/cloudfront/factory/cloudfront-functions.factory.js +27 -6
  4. package/dist/service/cloudfront/factory/cloudfront-functions.factory.js.map +1 -1
  5. package/dist/service/cloudfront/index.d.ts +1 -1
  6. package/dist/service/cloudfront/index.d.ts.map +1 -1
  7. package/dist/service/cloudfront/index.js +1 -1
  8. package/dist/service/cloudfront/index.js.map +1 -1
  9. package/package.json +7 -1
  10. package/.github/workflows/pr.yml +0 -54
  11. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  12. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  13. package/.idea/jsLinters/eslint.xml +0 -6
  14. package/.idea/modules.xml +0 -8
  15. package/.idea/prettier.xml +0 -7
  16. package/.idea/vcs.xml +0 -6
  17. package/.idea/yulin.iml +0 -8
  18. package/.nvmrc +0 -1
  19. package/.prettierrc +0 -4
  20. package/eslint.config.ts +0 -222
  21. package/pnpm-workspace.yaml +0 -23
  22. package/scripts/publish.sh +0 -14
  23. package/src/command/command-handler.ts +0 -3
  24. package/src/index.ts +0 -0
  25. package/src/service/cloudfront/factory/cloudfront-functions.factory.iso.test.ts +0 -10
  26. package/src/service/cloudfront/factory/cloudfront-functions.factory.ts +0 -34
  27. package/src/service/cloudfront/index.ts +0 -13
  28. package/src/service/cloudfront/typings/cloudfront-functions.ts +0 -48
  29. package/src/service/dynamodb/command/create-table/create-table.handler.ts +0 -61
  30. package/src/service/dynamodb/command/create-table/create-table.iso.test.ts +0 -99
  31. package/src/service/dynamodb/command/describe-table/describe-table.handler.ts +0 -52
  32. package/src/service/dynamodb/command/describe-table/describe-table.iso.test.ts +0 -82
  33. package/src/service/dynamodb/command/list-tables/list-tables.handler.ts +0 -53
  34. package/src/service/dynamodb/command/list-tables/list-tables.iso.test.ts +0 -119
  35. package/src/service/dynamodb/command/put-item/put-item.handler.ts +0 -56
  36. package/src/service/dynamodb/command/put-item/put-item.iso.test.ts +0 -354
  37. package/src/service/dynamodb/dynamodb.ts +0 -60
  38. package/src/service/dynamodb/index.ts +0 -0
  39. package/src/service/dynamodb/item/dynamodb-item-attribute.iso.test.ts +0 -19
  40. package/src/service/dynamodb/item/dynamodb-item-attribute.ts +0 -116
  41. package/src/service/dynamodb/item/dynamodb-item.ts +0 -39
  42. package/src/service/dynamodb/table/dynamodb-key-schema.ts +0 -94
  43. package/src/service/dynamodb/table/dynamodb-table.iso.test.ts +0 -46
  44. package/src/service/dynamodb/table/dynamodb-table.ts +0 -75
  45. package/src/service/organizations/index.ts +0 -0
  46. package/src/service/organizations/sim-aws-account.ts +0 -36
  47. package/src/service/s3/index.ts +0 -1
  48. package/src/util/background/background.iso.test.ts +0 -74
  49. package/src/util/background/background.ts +0 -62
  50. package/src/util/brand.type.ts +0 -11
  51. package/src/util/defined.ts +0 -15
  52. package/src/util/memo/memo.iso.test.ts +0 -43
  53. package/src/util/memo/memo.ts +0 -26
  54. package/src/util/sleep.ts +0 -16
  55. package/tsconfig.build.json +0 -13
  56. package/tsconfig.json +0 -39
  57. package/vitest.config.ts +0 -50
@@ -1,354 +0,0 @@
1
- import { describe, it } from "vitest";
2
- import { SimAwsAccount } from "../../../organizations/sim-aws-account.js";
3
- import { CreateTableCommand, PutItemCommand } from "@aws-sdk/client-dynamodb";
4
- import {
5
- assertBufferEqual,
6
- assertIdentical,
7
- assertInstanceOf,
8
- assertNonNullable,
9
- assertThrowsErrorAsync,
10
- assertTrue,
11
- assertStringIncludes,
12
- } from "@kensio/smartass";
13
-
14
- describe("DynamoDB PutItemCommand", () => {
15
- it("puts new Item into DynamoDB Table, returns attributes", async () => {
16
- const simAccount = new SimAwsAccount();
17
- const simDynamoDb = simAccount.getDynamoDb();
18
-
19
- await simDynamoDb.createTable(
20
- new CreateTableCommand({
21
- TableName: "FooTable",
22
- KeySchema: [{ AttributeName: "userId", KeyType: "HASH" }],
23
- }),
24
- );
25
-
26
- const putItemOutput = await simDynamoDb.putItem(
27
- new PutItemCommand({
28
- TableName: "FooTable",
29
- Item: {
30
- userId: { S: "4fad1110-e6dd-46ed-966b-356ba12f8102" },
31
-
32
- // Scalars
33
- userName: { S: "Foo McBar" },
34
- favouriteNumber: { N: "42" },
35
- likesPizza: { BOOL: true },
36
- missingValue: { NULL: true },
37
-
38
- // Binary
39
- profilePicture: {
40
- B: new Uint8Array([137, 80, 78, 71]), // "PNG" header bytes
41
- },
42
-
43
- // Sets
44
- favouriteColours: { SS: ["purple", "red"] },
45
- luckyNumbers: { NS: ["7", "13", "42"] },
46
- binaryTags: {
47
- BS: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
48
- },
49
-
50
- // List
51
- shoppingList: {
52
- L: [{ S: "milk" }, { S: "eggs" }],
53
- },
54
-
55
- // Map
56
- address: {
57
- M: {
58
- street: { S: "123 High Street" },
59
- city: { S: "London" },
60
- postcode: { S: "AB1 2CD" },
61
- coordinates: {
62
- M: {
63
- lat: { N: "51.5" },
64
- lon: { N: "-0.1" },
65
- },
66
- },
67
- },
68
- },
69
- },
70
- }),
71
- );
72
-
73
- assertNonNullable(putItemOutput.Attributes);
74
-
75
- // Scalars
76
- assertIdentical(
77
- putItemOutput.Attributes["userId"]?.S,
78
- "4fad1110-e6dd-46ed-966b-356ba12f8102",
79
- );
80
- assertIdentical(putItemOutput.Attributes["userName"]?.S, "Foo McBar");
81
- assertIdentical(putItemOutput.Attributes["favouriteNumber"]?.N, "42");
82
- assertTrue(putItemOutput.Attributes["likesPizza"]?.BOOL);
83
- assertTrue(putItemOutput.Attributes["missingValue"]?.NULL);
84
-
85
- // Binary
86
- assertBufferEqual(
87
- putItemOutput.Attributes["profilePicture"]?.B,
88
- new Uint8Array([137, 80, 78, 71]),
89
- );
90
-
91
- // Sets
92
- assertIdentical(
93
- putItemOutput.Attributes["favouriteColours"]?.SS?.[0],
94
- "purple",
95
- );
96
-
97
- // List
98
- assertIdentical(
99
- putItemOutput.Attributes["shoppingList"]?.L?.[0]?.S,
100
- "milk",
101
- );
102
-
103
- // Map
104
- assertIdentical(
105
- putItemOutput.Attributes["address"]?.M?.["street"]?.S,
106
- "123 High Street",
107
- );
108
- assertIdentical(putItemOutput.Attributes["address"].M["city"]?.S, "London");
109
- assertIdentical(
110
- putItemOutput.Attributes["address"].M["postcode"]?.S,
111
- "AB1 2CD",
112
- );
113
- assertIdentical(
114
- putItemOutput.Attributes["address"].M["coordinates"]?.M?.["lat"]?.N,
115
- "51.5",
116
- );
117
- assertIdentical(
118
- putItemOutput.Attributes["address"].M["coordinates"].M["lon"]?.N,
119
- "-0.1",
120
- );
121
-
122
- await simAccount.backgroundTasksComplete();
123
- });
124
-
125
- it("puts new Item into DynamoDB Table with partition key + sort key", async () => {
126
- const simAccount = new SimAwsAccount();
127
- const simDynamoDb = simAccount.getDynamoDb();
128
-
129
- await simDynamoDb.createTable(
130
- new CreateTableCommand({
131
- TableName: "FooTable",
132
- KeySchema: [
133
- { AttributeName: "userId", KeyType: "HASH" },
134
- { AttributeName: "orderId", KeyType: "RANGE" },
135
- ],
136
- }),
137
- );
138
-
139
- const putItemOutput = await simDynamoDb.putItem(
140
- new PutItemCommand({
141
- TableName: "FooTable",
142
- Item: {
143
- userId: { S: "06a3f1a5-df48-4951-8316-6c99ca1ec662" },
144
- orderId: { S: "736dbd1c-e02a-4526-8534-0f1ab9314db8" },
145
- somethingElse: { N: "12345" },
146
- },
147
- }),
148
- );
149
-
150
- assertNonNullable(putItemOutput.Attributes);
151
- assertIdentical(
152
- putItemOutput.Attributes["userId"]?.S,
153
- "06a3f1a5-df48-4951-8316-6c99ca1ec662",
154
- );
155
- assertIdentical(
156
- putItemOutput.Attributes["orderId"]?.S,
157
- "736dbd1c-e02a-4526-8534-0f1ab9314db8",
158
- );
159
- assertIdentical(putItemOutput.Attributes["somethingElse"]?.N, "12345");
160
- });
161
-
162
- it("rejects when missing partition key", async () => {
163
- const simAccount = new SimAwsAccount();
164
- const simDynamoDb = simAccount.getDynamoDb();
165
-
166
- await simDynamoDb.createTable(
167
- new CreateTableCommand({
168
- TableName: "FooTable",
169
- KeySchema: [{ AttributeName: "userId", KeyType: "HASH" }],
170
- }),
171
- );
172
-
173
- const error = await assertThrowsErrorAsync(async () => {
174
- await simDynamoDb.putItem(
175
- new PutItemCommand({
176
- TableName: "FooTable",
177
- Item: {
178
- orderId: { S: "da9ee033-2a2c-4b1e-942d-3f96f4ecdf06" },
179
- somethingElse: { N: "12345" },
180
- },
181
- }),
182
- );
183
- });
184
-
185
- assertInstanceOf(error, Error);
186
- assertStringIncludes(
187
- error.message,
188
- "DynamoDB Item partition key userId must be defined",
189
- );
190
- });
191
-
192
- it("rejects when missing sort key", async () => {
193
- const simAccount = new SimAwsAccount();
194
- const simDynamoDb = simAccount.getDynamoDb();
195
-
196
- await simDynamoDb.createTable(
197
- new CreateTableCommand({
198
- TableName: "FooTable",
199
- KeySchema: [
200
- { AttributeName: "userId", KeyType: "HASH" },
201
- { AttributeName: "orderId", KeyType: "RANGE" },
202
- ],
203
- }),
204
- );
205
-
206
- const error = await assertThrowsErrorAsync(async () => {
207
- await simDynamoDb.putItem(
208
- new PutItemCommand({
209
- TableName: "FooTable",
210
- Item: {
211
- userId: { S: "24ed2ef9-4276-457c-8c9b-a317bd788084" },
212
- somethingElse: { N: "12345" },
213
- },
214
- }),
215
- );
216
- });
217
-
218
- assertInstanceOf(error, Error);
219
- assertStringIncludes(
220
- error.message,
221
- "DynamoDB Item sort key orderId is undefined",
222
- );
223
- });
224
-
225
- it("rejects on invalid partition key type", async () => {
226
- const simAccount = new SimAwsAccount();
227
- const simDynamoDb = simAccount.getDynamoDb();
228
-
229
- await simDynamoDb.createTable(
230
- new CreateTableCommand({
231
- TableName: "FooTable",
232
- KeySchema: [{ AttributeName: "userId", KeyType: "HASH" }],
233
- }),
234
- );
235
-
236
- const error = await assertThrowsErrorAsync(async () => {
237
- await simDynamoDb.putItem(
238
- new PutItemCommand({
239
- TableName: "FooTable",
240
- Item: {
241
- userId: { BOOL: true },
242
- },
243
- }),
244
- );
245
- });
246
-
247
- assertInstanceOf(error, Error);
248
- assertStringIncludes(
249
- error.message,
250
- "DynamoDB Item partition key userId must be string or number",
251
- );
252
- });
253
-
254
- it("rejects on invalid sort key type", async () => {
255
- const simAccount = new SimAwsAccount();
256
- const simDynamoDb = simAccount.getDynamoDb();
257
-
258
- await simDynamoDb.createTable(
259
- new CreateTableCommand({
260
- TableName: "FooTable",
261
- KeySchema: [
262
- { AttributeName: "userId", KeyType: "HASH" },
263
- { AttributeName: "orderId", KeyType: "RANGE" },
264
- ],
265
- }),
266
- );
267
-
268
- const error = await assertThrowsErrorAsync(async () => {
269
- await simDynamoDb.putItem(
270
- new PutItemCommand({
271
- TableName: "FooTable",
272
- Item: {
273
- userId: { S: "ff8cc151-1b17-4d8e-8f98-ad631b6aefa7" },
274
- orderId: { BOOL: true },
275
- },
276
- }),
277
- );
278
- });
279
-
280
- assertInstanceOf(error, Error);
281
- assertStringIncludes(
282
- error.message,
283
- "DynamoDB Item sort key orderId must be string or number",
284
- );
285
- });
286
-
287
- it("rejects undefined table name", async () => {
288
- const simAccount = new SimAwsAccount();
289
- const simDynamoDb = simAccount.getDynamoDb();
290
-
291
- const error = await assertThrowsErrorAsync(async () => {
292
- await simDynamoDb.putItem(
293
- new PutItemCommand({
294
- TableName: undefined,
295
- Item: {
296
- userId: { S: "57bec277-9f94-4671-a592-d1c81df9860e" },
297
- },
298
- }),
299
- );
300
- });
301
-
302
- assertInstanceOf(error, Error);
303
- assertStringIncludes(
304
- error.message,
305
- "PutItemCommand.input.TableName is required",
306
- );
307
- });
308
-
309
- it("rejects non-existent table", async () => {
310
- const simAccount = new SimAwsAccount();
311
- const simDynamoDb = simAccount.getDynamoDb();
312
-
313
- const error = await assertThrowsErrorAsync(async () => {
314
- await simDynamoDb.putItem(
315
- new PutItemCommand({
316
- TableName: "FooTable",
317
- Item: {
318
- userId: { S: "6aaaba1a-cfe8-449c-8a7b-760e4f8025cb" },
319
- },
320
- }),
321
- );
322
- });
323
-
324
- assertInstanceOf(error, Error);
325
- assertStringIncludes(error.message, "No DynamoDB Table named FooTable");
326
- });
327
-
328
- it("rejects missing item", async () => {
329
- const simAccount = new SimAwsAccount();
330
- const simDynamoDb = simAccount.getDynamoDb();
331
-
332
- await simDynamoDb.createTable(
333
- new CreateTableCommand({
334
- TableName: "FooTable",
335
- KeySchema: [{ AttributeName: "userId", KeyType: "HASH" }],
336
- }),
337
- );
338
-
339
- const error = await assertThrowsErrorAsync(async () => {
340
- await simDynamoDb.putItem(
341
- new PutItemCommand({
342
- TableName: "FooTable",
343
- Item: undefined,
344
- }),
345
- );
346
- });
347
-
348
- assertInstanceOf(error, Error);
349
- assertStringIncludes(
350
- error.message,
351
- "PutItemCommand.input.Item is required",
352
- );
353
- });
354
- });
@@ -1,60 +0,0 @@
1
- import type {
2
- CreateTableCommand,
3
- CreateTableOutput,
4
- DescribeTableCommand,
5
- DescribeTableOutput,
6
- ListTablesCommand,
7
- ListTablesOutput,
8
- PutItemCommand,
9
- PutItemCommandOutput,
10
- } from "@aws-sdk/client-dynamodb";
11
- import type {
12
- DynamoDbTableName,
13
- SimDynamoDbTable,
14
- } from "./table/dynamodb-table.js";
15
- import { CreateTableCommandHandler } from "./command/create-table/create-table.handler.js";
16
- import type { BackgroundScheduler } from "../../util/background/background.js";
17
- import { ListTablesCommandHandler } from "./command/list-tables/list-tables.handler.js";
18
- import { DescribeTableCommandHandler } from "./command/describe-table/describe-table.handler.js";
19
- import { PutItemCommandHandler } from "./command/put-item/put-item.handler.js";
20
-
21
- /**
22
- * Simulated DynamoDB. Handles SDK commands. Emulates AWS behaviour and state.
23
- */
24
- export class SimDynamoDb {
25
- private readonly tables = new Map<DynamoDbTableName, SimDynamoDbTable>();
26
-
27
- constructor(private readonly background: BackgroundScheduler) {}
28
-
29
- /**
30
- * Handle a Create Table Command from the SDK.
31
- */
32
- async createTable(cmd: CreateTableCommand): Promise<CreateTableOutput> {
33
- const handler = new CreateTableCommandHandler(this.tables, this.background);
34
- return await handler.handle(cmd);
35
- }
36
-
37
- /**
38
- * Handle a List Tables Command from the SDK.
39
- */
40
- async listTables(cmd: ListTablesCommand): Promise<ListTablesOutput> {
41
- const handler = new ListTablesCommandHandler(this.tables);
42
- return await handler.handle(cmd);
43
- }
44
-
45
- /**
46
- * Handle a Describe Table Command from the SDK.
47
- */
48
- async describeTable(cmd: DescribeTableCommand): Promise<DescribeTableOutput> {
49
- const handler = new DescribeTableCommandHandler(this.tables);
50
- return await handler.handle(cmd);
51
- }
52
-
53
- /**
54
- * Handle a Put Item Command from the SDK.
55
- */
56
- async putItem(cmd: PutItemCommand): Promise<PutItemCommandOutput> {
57
- const handler = new PutItemCommandHandler(this.tables);
58
- return await handler.handle(cmd);
59
- }
60
- }
File without changes
@@ -1,19 +0,0 @@
1
- import { describe, it } from "vitest";
2
- import {
3
- assertInstanceOf,
4
- assertStringIncludes,
5
- assertThrowsError,
6
- } from "@kensio/smartass";
7
- import { DynamoDBItemAttribute } from "./dynamodb-item-attribute.js";
8
-
9
- describe("DynamoDB Item Attribute", () => {
10
- it("rejects unrecognised attribute type", () => {
11
- const error = assertThrowsError(() => {
12
- // @ts-expect-error testing invalid DDB attribute type key
13
- DynamoDBItemAttribute.fromAttributeValue({ BAD: "foobar" });
14
- });
15
-
16
- assertInstanceOf(error, Error);
17
- assertStringIncludes(error.message, "Unsupported AttributeValue type");
18
- });
19
- });
@@ -1,116 +0,0 @@
1
- import type { AttributeValue } from "@aws-sdk/client-dynamodb";
2
-
3
- export type DynamoDBAttrType =
4
- | boolean
5
- | null
6
- | number
7
- | string
8
- | Uint8Array
9
- | Set<string>
10
- | Set<number>
11
- | Set<Uint8Array>
12
- | DynamoDBAttrType[]
13
- | { [key: string]: DynamoDBAttrType };
14
-
15
- /**
16
- * A single attribute of a DynamoDB Item.
17
- */
18
- export class DynamoDBItemAttribute {
19
- constructor(readonly value: DynamoDBAttrType) {}
20
-
21
- /**
22
- * Convert a DynamoDB AttributeValue structure to a DynamoDBItemAttribute
23
- * instance.
24
- */
25
- static fromAttributeValue(value: AttributeValue): DynamoDBItemAttribute {
26
- if (value.BOOL !== undefined) {
27
- return new DynamoDBItemAttribute(value.BOOL);
28
- }
29
- if (value.NULL !== undefined) {
30
- return new DynamoDBItemAttribute(null);
31
- }
32
- if (value.S !== undefined) {
33
- return new DynamoDBItemAttribute(value.S);
34
- }
35
- if (value.N !== undefined) {
36
- return new DynamoDBItemAttribute(Number(value.N));
37
- }
38
- if (value.B !== undefined) {
39
- return new DynamoDBItemAttribute(value.B);
40
- }
41
- if (value.SS !== undefined) {
42
- return new DynamoDBItemAttribute(new Set(value.SS));
43
- }
44
- if (value.NS !== undefined) {
45
- return new DynamoDBItemAttribute(new Set(value.NS.map(Number)));
46
- }
47
- if (value.BS !== undefined) {
48
- return new DynamoDBItemAttribute(new Set(value.BS));
49
- }
50
- if (value.L !== undefined) {
51
- return new DynamoDBItemAttribute(
52
- value.L.map((el) => DynamoDBItemAttribute.fromAttributeValue(el).value),
53
- );
54
- }
55
- if (value.M !== undefined) {
56
- return new DynamoDBItemAttribute(
57
- Object.fromEntries(
58
- Object.entries(value.M).map(([key, val]) => [
59
- key,
60
- DynamoDBItemAttribute.fromAttributeValue(val).value,
61
- ]),
62
- ),
63
- );
64
- }
65
- throw new Error(
66
- `Unsupported AttributeValue type: ${JSON.stringify(value)}`,
67
- );
68
- }
69
-
70
- /**
71
- * Convert this DynamoDBItemAttribute to a DynamoDB AttributeValue structure.
72
- */
73
- toAttributeValue(): AttributeValue {
74
- const value = this.value;
75
-
76
- if (value === null) {
77
- return { NULL: true };
78
- }
79
- if (typeof value === "string") {
80
- return { S: value };
81
- }
82
- if (typeof value === "number") {
83
- return { N: String(value) };
84
- }
85
- if (typeof value === "boolean") {
86
- return { BOOL: value };
87
- }
88
- if (ArrayBuffer.isView(value)) {
89
- return { B: value };
90
- }
91
- if (Array.isArray(value)) {
92
- return {
93
- L: value.map((el) => new DynamoDBItemAttribute(el).toAttributeValue()),
94
- };
95
- }
96
- if (value instanceof Set) {
97
- const firstValue = value.values().next().value;
98
- if (firstValue !== undefined && ArrayBuffer.isView(firstValue)) {
99
- return { BS: [...value] as Uint8Array[] };
100
- }
101
- if (typeof firstValue === "number") {
102
- return { NS: [...value].map(String) };
103
- }
104
- return { SS: [...value] as string[] };
105
- }
106
-
107
- return {
108
- M: Object.fromEntries(
109
- Object.entries(value).map(([key, val]) => [
110
- key,
111
- new DynamoDBItemAttribute(val).toAttributeValue(),
112
- ]),
113
- ),
114
- };
115
- }
116
- }
@@ -1,39 +0,0 @@
1
- import type { AttributeValue } from "@aws-sdk/client-dynamodb";
2
- import { DynamoDBItemAttribute } from "./dynamodb-item-attribute.js";
3
-
4
- /**
5
- * A single Item in a DynamoDB Table.
6
- */
7
- export class DynamoDbItem {
8
- constructor(
9
- readonly attributes: Record<string, DynamoDBItemAttribute> = {},
10
- ) {}
11
-
12
- /**
13
- * Convert an AttributeValue structure to a DynamoDbItem instance.
14
- */
15
- static fromAttributeValues(
16
- attributeValues: Record<string, AttributeValue>,
17
- ): DynamoDbItem {
18
- return new DynamoDbItem(
19
- Object.fromEntries(
20
- Object.entries(attributeValues).map(([key, value]) => [
21
- key,
22
- DynamoDBItemAttribute.fromAttributeValue(value),
23
- ]),
24
- ),
25
- );
26
- }
27
-
28
- /**
29
- * Convert this DynamoDbItem to an AttributeValue structure.
30
- */
31
- toAttributeValues(): Record<string, AttributeValue> {
32
- return Object.fromEntries(
33
- Object.entries(this.attributes).map(([key, value]) => [
34
- key,
35
- value.toAttributeValue(),
36
- ]),
37
- );
38
- }
39
- }
@@ -1,94 +0,0 @@
1
- import type { CreateTableInput, KeyType } from "@aws-sdk/client-dynamodb";
2
- import { assertDefined } from "../../../util/defined.js";
3
- import type { DynamoDbItem } from "../item/dynamodb-item.js";
4
- import type { DynamoDBAttrType } from "../item/dynamodb-item-attribute.js";
5
-
6
- type DynamoDbKey = string | number;
7
-
8
- /**
9
- * Extractor for DynamoDB KeySchema from CreateTableCommand input.
10
- *
11
- * https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_KeySchemaElement.html
12
- */
13
- export class DynamoDbKeySchema {
14
- public readonly partitionKey: { AttributeName: string; KeyType: KeyType };
15
-
16
- public readonly sortKey?: { AttributeName: string; KeyType: KeyType };
17
-
18
- constructor(createTableInput: Pick<CreateTableInput, "KeySchema">) {
19
- assertDefined(createTableInput.KeySchema, "createTableInput.KeySchema");
20
-
21
- const partitionKeyElement = createTableInput.KeySchema.find(
22
- (el) => el.KeyType === "HASH",
23
- );
24
- assertDefined(
25
- partitionKeyElement,
26
- '"CreateTableInput.KeySchema partition key (KeyType=HASH)',
27
- );
28
- assertDefined(
29
- partitionKeyElement.AttributeName,
30
- "Partition Key AttributeName",
31
- );
32
- assertDefined(partitionKeyElement.KeyType, "Partition Key KeyType");
33
- this.partitionKey = {
34
- AttributeName: partitionKeyElement.AttributeName,
35
- KeyType: partitionKeyElement.KeyType,
36
- };
37
-
38
- const sortKeyElement = createTableInput.KeySchema.find(
39
- (el) => el.KeyType === "RANGE",
40
- );
41
- if (sortKeyElement === undefined) {
42
- return;
43
- }
44
- assertDefined(sortKeyElement.AttributeName, "Sort Key AttributeName");
45
- assertDefined(sortKeyElement.KeyType, "Sort Key KeyType");
46
- this.sortKey = {
47
- AttributeName: sortKeyElement.AttributeName,
48
- KeyType: sortKeyElement.KeyType,
49
- };
50
- }
51
-
52
- /**
53
- * Make a primary key string for an item based on this key schema.
54
- */
55
- makeItemKey(item: DynamoDbItem): string {
56
- const partitionKeyAttr = item.attributes[this.partitionKey.AttributeName];
57
- assertDefined(
58
- partitionKeyAttr,
59
- `DynamoDB Item partition key ${this.partitionKey.AttributeName}`,
60
- );
61
- const partitionKey = partitionKeyAttr.value;
62
- if (!DynamoDbKeySchema.canBeDynamoDbKey(partitionKey)) {
63
- throw new TypeError(
64
- `DynamoDB Item partition key ${this.partitionKey.AttributeName} must be string or number`,
65
- );
66
- }
67
-
68
- const keyParts: Record<string, DynamoDbKey> = { partitionKey };
69
-
70
- if (this.sortKey?.AttributeName !== undefined) {
71
- const sortKey = item.attributes[this.sortKey.AttributeName];
72
- if (sortKey === undefined) {
73
- throw new TypeError(
74
- `DynamoDB Item sort key ${this.sortKey.AttributeName} is undefined`,
75
- );
76
- }
77
- if (!DynamoDbKeySchema.canBeDynamoDbKey(sortKey.value)) {
78
- throw new TypeError(
79
- `DynamoDB Item sort key ${this.sortKey.AttributeName} must be string or number`,
80
- );
81
- }
82
- keyParts[this.sortKey.AttributeName] = sortKey.value;
83
- }
84
-
85
- return JSON.stringify(keyParts);
86
- }
87
-
88
- /**
89
- * Check if a given value can be used as a DynamoDB partition key or sort key.
90
- */
91
- static canBeDynamoDbKey(value: DynamoDBAttrType): value is DynamoDbKey {
92
- return typeof value === "string" || typeof value === "number";
93
- }
94
- }