dynamodb-expression-builder 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/index.cjs +615 -9
- package/dist/index.d.cts +51 -3
- package/dist/index.d.ts +51 -3
- package/dist/index.js +602 -10
- package/package.json +7 -2
package/dist/index.cjs
CHANGED
|
@@ -154,6 +154,24 @@ const FILTER_OPERATORS = [
|
|
|
154
154
|
"L"
|
|
155
155
|
]
|
|
156
156
|
},
|
|
157
|
+
{
|
|
158
|
+
value: "not_contains",
|
|
159
|
+
label: "Not Contains",
|
|
160
|
+
symbol: "∌",
|
|
161
|
+
wireForm: "NOT_CONTAINS",
|
|
162
|
+
requiresValue: true,
|
|
163
|
+
requiresValue2: false,
|
|
164
|
+
typeOptional: false,
|
|
165
|
+
keyAllowedTypes: [],
|
|
166
|
+
scanAllowedTypes: [
|
|
167
|
+
"S",
|
|
168
|
+
"B",
|
|
169
|
+
"SS",
|
|
170
|
+
"NS",
|
|
171
|
+
"BS",
|
|
172
|
+
"L"
|
|
173
|
+
]
|
|
174
|
+
},
|
|
157
175
|
{
|
|
158
176
|
value: "begins_with",
|
|
159
177
|
label: "Begins With",
|
|
@@ -370,6 +388,9 @@ function buildOne(row, index, prefix, names, typedValues) {
|
|
|
370
388
|
case "CONTAINS":
|
|
371
389
|
typedValues[valueRef] = makeTypedValue(elementType(row.type), row.value);
|
|
372
390
|
return `contains(${nameRef}, ${valueRef})`;
|
|
391
|
+
case "NOT_CONTAINS":
|
|
392
|
+
typedValues[valueRef] = makeTypedValue(elementType(row.type), row.value);
|
|
393
|
+
return `NOT contains(${nameRef}, ${valueRef})`;
|
|
373
394
|
case "BEGINS_WITH":
|
|
374
395
|
typedValues[valueRef] = single$1(row);
|
|
375
396
|
return `begins_with(${nameRef}, ${valueRef})`;
|
|
@@ -726,7 +747,7 @@ function hasBinaryValue(request) {
|
|
|
726
747
|
//#endregion
|
|
727
748
|
//#region src/emit/sdk-v3.ts
|
|
728
749
|
/** Operation → the `@aws-sdk/client-dynamodb` command class name. */
|
|
729
|
-
const COMMAND_BY_OP = {
|
|
750
|
+
const COMMAND_BY_OP$1 = {
|
|
730
751
|
GetItem: "GetItemCommand",
|
|
731
752
|
Query: "QueryCommand",
|
|
732
753
|
Scan: "ScanCommand",
|
|
@@ -784,11 +805,11 @@ function jsLiteral(value, indent) {
|
|
|
784
805
|
}
|
|
785
806
|
/** Emit the `new <Op>Command({...})` source snippet for a canonical request. */
|
|
786
807
|
function emitSdkV3(request) {
|
|
787
|
-
return `new ${COMMAND_BY_OP[request.operation]}(${jsLiteral(buildSdkV3Params(request), 0)})`;
|
|
808
|
+
return `new ${COMMAND_BY_OP$1[request.operation]}(${jsLiteral(buildSdkV3Params(request), 0)})`;
|
|
788
809
|
}
|
|
789
810
|
/** The `@aws-sdk/client-dynamodb` command class name for an operation. */
|
|
790
811
|
function sdkV3CommandName(operation) {
|
|
791
|
-
return COMMAND_BY_OP[operation];
|
|
812
|
+
return COMMAND_BY_OP$1[operation];
|
|
792
813
|
}
|
|
793
814
|
/**
|
|
794
815
|
* Render an arbitrary params value as the same pretty-printed JS literal
|
|
@@ -967,6 +988,7 @@ function predicate(row) {
|
|
|
967
988
|
case "BETWEEN": return `${id} BETWEEN ${literal(makeTypedValue(row.type, row.value))} AND ${literal(makeTypedValue(row.type, row.value2 ?? ""))}`;
|
|
968
989
|
case "BEGINS_WITH": return `begins_with(${id}, ${literal(single(row))})`;
|
|
969
990
|
case "CONTAINS": return `contains(${id}, ${literal(makeTypedValue(elementType(row.type), row.value))})`;
|
|
991
|
+
case "NOT_CONTAINS": return `NOT contains(${id}, ${literal(makeTypedValue(elementType(row.type), row.value))})`;
|
|
970
992
|
case "IN": return `${id} IN (${(row.values ?? (row.value ? [row.value] : [])).map((m) => literal(makeTypedValue(row.type, m))).join(", ")})`;
|
|
971
993
|
case "EXISTS": return `${id} IS NOT MISSING`;
|
|
972
994
|
case "NOT_EXISTS": return `${id} IS MISSING`;
|
|
@@ -1095,7 +1117,7 @@ const REQUEST_CLASS_BY_OP$1 = {
|
|
|
1095
1117
|
Delete: "DeleteItemRequest"
|
|
1096
1118
|
};
|
|
1097
1119
|
/** Operation → the `DynamoDbClient` method. */
|
|
1098
|
-
const CLIENT_METHOD_BY_OP$
|
|
1120
|
+
const CLIENT_METHOD_BY_OP$6 = {
|
|
1099
1121
|
GetItem: "getItem",
|
|
1100
1122
|
Query: "query",
|
|
1101
1123
|
Scan: "scan",
|
|
@@ -1109,7 +1131,7 @@ function javaRequestClassName(operation) {
|
|
|
1109
1131
|
}
|
|
1110
1132
|
/** The `DynamoDbClient` method name for an operation (`query`, …). */
|
|
1111
1133
|
function javaClientMethodName(operation) {
|
|
1112
|
-
return CLIENT_METHOD_BY_OP$
|
|
1134
|
+
return CLIENT_METHOD_BY_OP$6[operation];
|
|
1113
1135
|
}
|
|
1114
1136
|
/** Java string literal — `JSON.stringify` escapes are all valid Java escapes. */
|
|
1115
1137
|
function javaString(value) {
|
|
@@ -1188,7 +1210,7 @@ const INPUT_TYPE_BY_OP = {
|
|
|
1188
1210
|
Delete: "DeleteItemInput"
|
|
1189
1211
|
};
|
|
1190
1212
|
/** Operation → the `dynamodb.Client` method. */
|
|
1191
|
-
const CLIENT_METHOD_BY_OP$
|
|
1213
|
+
const CLIENT_METHOD_BY_OP$5 = {
|
|
1192
1214
|
GetItem: "GetItem",
|
|
1193
1215
|
Query: "Query",
|
|
1194
1216
|
Scan: "Scan",
|
|
@@ -1202,7 +1224,7 @@ function goInputTypeName(operation) {
|
|
|
1202
1224
|
}
|
|
1203
1225
|
/** The `dynamodb.Client` method name for an operation. */
|
|
1204
1226
|
function goClientMethodName(operation) {
|
|
1205
|
-
return CLIENT_METHOD_BY_OP$
|
|
1227
|
+
return CLIENT_METHOD_BY_OP$5[operation];
|
|
1206
1228
|
}
|
|
1207
1229
|
/** Go string literal — `JSON.stringify` escapes are all valid Go escapes. */
|
|
1208
1230
|
function goString(value) {
|
|
@@ -1292,7 +1314,7 @@ const REQUEST_CLASS_BY_OP = {
|
|
|
1292
1314
|
Delete: "DeleteItemRequest"
|
|
1293
1315
|
};
|
|
1294
1316
|
/** Operation → the async `AmazonDynamoDBClient` method. */
|
|
1295
|
-
const CLIENT_METHOD_BY_OP = {
|
|
1317
|
+
const CLIENT_METHOD_BY_OP$4 = {
|
|
1296
1318
|
GetItem: "GetItemAsync",
|
|
1297
1319
|
Query: "QueryAsync",
|
|
1298
1320
|
Scan: "ScanAsync",
|
|
@@ -1306,7 +1328,7 @@ function dotnetRequestClassName(operation) {
|
|
|
1306
1328
|
}
|
|
1307
1329
|
/** The async client method name for an operation (`QueryAsync`, …). */
|
|
1308
1330
|
function dotnetClientMethodName(operation) {
|
|
1309
|
-
return CLIENT_METHOD_BY_OP[operation];
|
|
1331
|
+
return CLIENT_METHOD_BY_OP$4[operation];
|
|
1310
1332
|
}
|
|
1311
1333
|
/** C# string literal — `JSON.stringify` escapes are all valid C# escapes. */
|
|
1312
1334
|
function csString(value) {
|
|
@@ -1373,6 +1395,102 @@ function emitDotnet(request) {
|
|
|
1373
1395
|
return renderCsRequest(request, "");
|
|
1374
1396
|
}
|
|
1375
1397
|
|
|
1398
|
+
//#endregion
|
|
1399
|
+
//#region src/emit/rust.ts
|
|
1400
|
+
/** Operation → the `aws_sdk_dynamodb::Client` fluent method. */
|
|
1401
|
+
const CLIENT_METHOD_BY_OP$3 = {
|
|
1402
|
+
GetItem: "get_item",
|
|
1403
|
+
Query: "query",
|
|
1404
|
+
Scan: "scan",
|
|
1405
|
+
Update: "update_item",
|
|
1406
|
+
Put: "put_item",
|
|
1407
|
+
Delete: "delete_item"
|
|
1408
|
+
};
|
|
1409
|
+
/** The `Client` method name (snake_case) for an operation. */
|
|
1410
|
+
function rustClientMethodName(operation) {
|
|
1411
|
+
return CLIENT_METHOD_BY_OP$3[operation];
|
|
1412
|
+
}
|
|
1413
|
+
/** Rust string literal — JSON escapes with the three Rust-incompatible ones fixed. */
|
|
1414
|
+
function rustString(value) {
|
|
1415
|
+
return JSON.stringify(value).replace(/\\b/g, "\\u{0008}").replace(/\\f/g, "\\u{000c}").replace(/\\u([0-9a-fA-F]{4})/g, "\\u{$1}");
|
|
1416
|
+
}
|
|
1417
|
+
/** `"…".to_string()` — the owned String the AttributeValue constructors take. */
|
|
1418
|
+
function rustOwned(value) {
|
|
1419
|
+
return `${rustString(value)}.to_string()`;
|
|
1420
|
+
}
|
|
1421
|
+
/** Decode canonical base64 into a `Blob::new(vec![0x…])` (fail-loud on bad input). */
|
|
1422
|
+
function rustBlob(base64) {
|
|
1423
|
+
let raw;
|
|
1424
|
+
try {
|
|
1425
|
+
raw = atob(base64);
|
|
1426
|
+
} catch {
|
|
1427
|
+
throw new Error(`invalid base64 in a binary (B/BS) value: ${base64}`);
|
|
1428
|
+
}
|
|
1429
|
+
return `Blob::new(vec![${Array.from(raw, (c) => `0x${c.charCodeAt(0).toString(16).padStart(2, "0")}`).join(", ")}])`;
|
|
1430
|
+
}
|
|
1431
|
+
/** Render one wire AttributeValue as an `AttributeValue::…` constructor. */
|
|
1432
|
+
function renderRustAv(av) {
|
|
1433
|
+
if ("S" in av) return `AttributeValue::S(${rustOwned(av.S)})`;
|
|
1434
|
+
if ("N" in av) return `AttributeValue::N(${rustOwned(av.N)})`;
|
|
1435
|
+
if ("B" in av) return `AttributeValue::B(${rustBlob(av.B)})`;
|
|
1436
|
+
if ("BOOL" in av) return `AttributeValue::Bool(${av.BOOL})`;
|
|
1437
|
+
if ("SS" in av) return `AttributeValue::Ss(vec![${av.SS.map(rustOwned).join(", ")}])`;
|
|
1438
|
+
if ("NS" in av) return `AttributeValue::Ns(vec![${av.NS.map(rustOwned).join(", ")}])`;
|
|
1439
|
+
if ("BS" in av) return `AttributeValue::Bs(vec![${av.BS.map(rustBlob).join(", ")}])`;
|
|
1440
|
+
return "AttributeValue::Null(true)";
|
|
1441
|
+
}
|
|
1442
|
+
/** One `.method(key, av)` line per entry of a typed map. */
|
|
1443
|
+
function avEntryLines(method, map, indent) {
|
|
1444
|
+
return Object.entries(typedMapToAvMap(map)).map(([name, av]) => `${indent}.${method}(${rustString(name)}, ${renderRustAv(av)})`);
|
|
1445
|
+
}
|
|
1446
|
+
/**
|
|
1447
|
+
* Render the fluent builder chain for a request — every line at `indent`,
|
|
1448
|
+
* starting with `.{op}()` and ending BEFORE `.send()` so callers own the
|
|
1449
|
+
* terminal (the bare emitter awaits inline; the program emitter may hand the
|
|
1450
|
+
* chain to `into_paginator()` instead). Exported for the program emitter.
|
|
1451
|
+
*/
|
|
1452
|
+
function renderRustBuilder(request, indent) {
|
|
1453
|
+
const lines = [`${indent}.${CLIENT_METHOD_BY_OP$3[request.operation]}()`];
|
|
1454
|
+
lines.push(`${indent}.table_name(${rustString(request.tableName)})`);
|
|
1455
|
+
if (request.indexName) lines.push(`${indent}.index_name(${rustString(request.indexName)})`);
|
|
1456
|
+
if (request.key) lines.push(...avEntryLines("key", request.key, indent));
|
|
1457
|
+
if (request.item) lines.push(...avEntryLines("item", request.item, indent));
|
|
1458
|
+
if (request.keyConditionExpression) lines.push(`${indent}.key_condition_expression(${rustString(request.keyConditionExpression)})`);
|
|
1459
|
+
if (request.updateExpression) lines.push(`${indent}.update_expression(${rustString(request.updateExpression)})`);
|
|
1460
|
+
if (request.conditionExpression) lines.push(`${indent}.condition_expression(${rustString(request.conditionExpression)})`);
|
|
1461
|
+
if (request.filterExpression) lines.push(`${indent}.filter_expression(${rustString(request.filterExpression)})`);
|
|
1462
|
+
if (request.projectionExpression) lines.push(`${indent}.projection_expression(${rustString(request.projectionExpression)})`);
|
|
1463
|
+
if (request.names) lines.push(...Object.entries(request.names).map(([alias, name]) => `${indent}.expression_attribute_names(${rustString(alias)}, ${rustString(name)})`));
|
|
1464
|
+
if (request.typedValues) lines.push(...avEntryLines("expression_attribute_values", request.typedValues, indent));
|
|
1465
|
+
if (request.limit !== void 0) lines.push(`${indent}.limit(${request.limit})`);
|
|
1466
|
+
if (request.consistentRead) lines.push(`${indent}.consistent_read(true)`);
|
|
1467
|
+
if (request.scanIndexForward === false) lines.push(`${indent}.scan_index_forward(false)`);
|
|
1468
|
+
if (request.exclusiveStartKey) lines.push(...avEntryLines("exclusive_start_key", request.exclusiveStartKey, indent));
|
|
1469
|
+
return lines;
|
|
1470
|
+
}
|
|
1471
|
+
/** Does this request build any `AttributeValue`? Drives the program emitter's imports. */
|
|
1472
|
+
function rustUsesAttributeValue(request) {
|
|
1473
|
+
return request.key !== void 0 || request.item !== void 0 || request.typedValues !== void 0 || request.exclusiveStartKey !== void 0;
|
|
1474
|
+
}
|
|
1475
|
+
/** Does this request build any binary Blob? Drives the `primitives::Blob` import. */
|
|
1476
|
+
function rustUsesBlob(request) {
|
|
1477
|
+
return [
|
|
1478
|
+
request.key,
|
|
1479
|
+
request.item,
|
|
1480
|
+
request.typedValues,
|
|
1481
|
+
request.exclusiveStartKey
|
|
1482
|
+
].some((map) => map && Object.values(typedMapToAvMap(map)).some((av) => "B" in av || "BS" in av));
|
|
1483
|
+
}
|
|
1484
|
+
/** Emit the bare fluent call for a canonical request (awaited, `?`-propagated). */
|
|
1485
|
+
function emitRust(request) {
|
|
1486
|
+
return [
|
|
1487
|
+
"let response = client",
|
|
1488
|
+
...renderRustBuilder(request, " "),
|
|
1489
|
+
" .send()",
|
|
1490
|
+
" .await?;"
|
|
1491
|
+
].join("\n");
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1376
1494
|
//#endregion
|
|
1377
1495
|
//#region src/emit/ddbtoolbox.ts
|
|
1378
1496
|
/** Key attr DynamoDB type (S/N/B) → the Table `type` string dynamodb-toolbox wants. */
|
|
@@ -1438,6 +1556,7 @@ function renderCondition(f) {
|
|
|
1438
1556
|
if (f.operator === "exists") return `{ attr: ${attr}, exists: true }`;
|
|
1439
1557
|
if (f.operator === "not_exists") return `{ attr: ${attr}, exists: false }`;
|
|
1440
1558
|
if (f.operator === "contains") return `{ attr: ${attr}, contains: ${val()} }`;
|
|
1559
|
+
if (f.operator === "not_contains") return `{ not: { attr: ${attr}, contains: ${val()} } }`;
|
|
1441
1560
|
if (f.operator === "begins_with") return `{ attr: ${attr}, beginsWith: ${val()} }`;
|
|
1442
1561
|
if (f.operator === "between") return `{ attr: ${attr}, between: [${renderNativeValue(scalar(f.type, f.value))}, ${renderNativeValue(scalar(f.type, f.value2 ?? ""))}] }`;
|
|
1443
1562
|
if (f.operator === "in") return `{ attr: ${attr}, in: [${(f.values ?? []).map((v) => renderNativeValue(scalar(f.type, v))).join(", ")}] }`;
|
|
@@ -1583,6 +1702,292 @@ function emitDdbToolboxProgram(request, paginate) {
|
|
|
1583
1702
|
].filter((l) => l !== null).join("\n");
|
|
1584
1703
|
}
|
|
1585
1704
|
|
|
1705
|
+
//#endregion
|
|
1706
|
+
//#region src/emit/docclient.ts
|
|
1707
|
+
/** Operation → the `@aws-sdk/lib-dynamodb` command class. */
|
|
1708
|
+
const COMMAND_BY_OP = {
|
|
1709
|
+
GetItem: "GetCommand",
|
|
1710
|
+
Query: "QueryCommand",
|
|
1711
|
+
Scan: "ScanCommand",
|
|
1712
|
+
Update: "UpdateCommand",
|
|
1713
|
+
Put: "PutCommand",
|
|
1714
|
+
Delete: "DeleteCommand"
|
|
1715
|
+
};
|
|
1716
|
+
/** The lib-dynamodb command class name for an operation. */
|
|
1717
|
+
function docClientCommandName(operation) {
|
|
1718
|
+
return COMMAND_BY_OP[operation];
|
|
1719
|
+
}
|
|
1720
|
+
/** Render a typed map as a native-value object literal, one entry per line. */
|
|
1721
|
+
function renderNativeMap(map, indent) {
|
|
1722
|
+
const inner = `${indent} `;
|
|
1723
|
+
return `{\n${Object.entries(map).map(([name, tv]) => `${inner}${JSON.stringify(name)}: ${renderNativeValue(tv)},`).join("\n")}\n${indent}}`;
|
|
1724
|
+
}
|
|
1725
|
+
/** Render the plain string map (`ExpressionAttributeNames`). */
|
|
1726
|
+
function renderNameMap$3(map, indent) {
|
|
1727
|
+
const inner = `${indent} `;
|
|
1728
|
+
return `{\n${Object.entries(map).map(([alias, name]) => `${inner}${JSON.stringify(alias)}: ${JSON.stringify(name)},`).join("\n")}\n${indent}}`;
|
|
1729
|
+
}
|
|
1730
|
+
/**
|
|
1731
|
+
* Render the command's params object literal, one field per line at
|
|
1732
|
+
* `indent + 2`. Exported for the program emitter.
|
|
1733
|
+
*/
|
|
1734
|
+
function renderDocClientParams(request, indent) {
|
|
1735
|
+
const pad = `${indent} `;
|
|
1736
|
+
const fields = [`TableName: ${JSON.stringify(request.tableName)},`];
|
|
1737
|
+
if (request.indexName) fields.push(`IndexName: ${JSON.stringify(request.indexName)},`);
|
|
1738
|
+
if (request.key) fields.push(`Key: ${renderNativeMap(request.key, pad)},`);
|
|
1739
|
+
if (request.item) fields.push(`Item: ${renderNativeMap(request.item, pad)},`);
|
|
1740
|
+
if (request.keyConditionExpression) fields.push(`KeyConditionExpression: ${JSON.stringify(request.keyConditionExpression)},`);
|
|
1741
|
+
if (request.updateExpression) fields.push(`UpdateExpression: ${JSON.stringify(request.updateExpression)},`);
|
|
1742
|
+
if (request.conditionExpression) fields.push(`ConditionExpression: ${JSON.stringify(request.conditionExpression)},`);
|
|
1743
|
+
if (request.filterExpression) fields.push(`FilterExpression: ${JSON.stringify(request.filterExpression)},`);
|
|
1744
|
+
if (request.projectionExpression) fields.push(`ProjectionExpression: ${JSON.stringify(request.projectionExpression)},`);
|
|
1745
|
+
if (request.names) fields.push(`ExpressionAttributeNames: ${renderNameMap$3(request.names, pad)},`);
|
|
1746
|
+
if (request.typedValues) fields.push(`ExpressionAttributeValues: ${renderNativeMap(request.typedValues, pad)},`);
|
|
1747
|
+
if (request.limit !== void 0) fields.push(`Limit: ${request.limit},`);
|
|
1748
|
+
if (request.consistentRead) fields.push("ConsistentRead: true,");
|
|
1749
|
+
if (request.scanIndexForward === false) fields.push("ScanIndexForward: false,");
|
|
1750
|
+
if (request.exclusiveStartKey) fields.push(`ExclusiveStartKey: ${renderNativeMap(request.exclusiveStartKey, pad)},`);
|
|
1751
|
+
return [
|
|
1752
|
+
"{",
|
|
1753
|
+
...fields.map((f) => `${pad}${f}`),
|
|
1754
|
+
`${indent}}`
|
|
1755
|
+
].join("\n");
|
|
1756
|
+
}
|
|
1757
|
+
/** Emit the bare `new XCommand({…})` snippet with native values. */
|
|
1758
|
+
function emitDocClient(request) {
|
|
1759
|
+
return `new ${COMMAND_BY_OP[request.operation]}(${renderDocClientParams(request, "")})`;
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
//#endregion
|
|
1763
|
+
//#region src/emit/kotlin.ts
|
|
1764
|
+
/** Operation → the `DynamoDbClient` suspend function. */
|
|
1765
|
+
const CLIENT_METHOD_BY_OP$2 = {
|
|
1766
|
+
GetItem: "getItem",
|
|
1767
|
+
Query: "query",
|
|
1768
|
+
Scan: "scan",
|
|
1769
|
+
Update: "updateItem",
|
|
1770
|
+
Put: "putItem",
|
|
1771
|
+
Delete: "deleteItem"
|
|
1772
|
+
};
|
|
1773
|
+
/** The client method name (camelCase) for an operation. */
|
|
1774
|
+
function kotlinClientMethodName(operation) {
|
|
1775
|
+
return CLIENT_METHOD_BY_OP$2[operation];
|
|
1776
|
+
}
|
|
1777
|
+
/** Kotlin string literal — JSON escapes are valid Kotlin escapes, plus `$` must
|
|
1778
|
+
* be escaped (string templates). */
|
|
1779
|
+
function ktString(value) {
|
|
1780
|
+
return JSON.stringify(value).replace(/\$/g, "\\$");
|
|
1781
|
+
}
|
|
1782
|
+
/** Decode canonical base64 into a `byteArrayOf(0x…)` literal (fail-loud). */
|
|
1783
|
+
function ktBytes(base64) {
|
|
1784
|
+
let raw;
|
|
1785
|
+
try {
|
|
1786
|
+
raw = atob(base64);
|
|
1787
|
+
} catch {
|
|
1788
|
+
throw new Error(`invalid base64 in a binary (B/BS) value: ${base64}`);
|
|
1789
|
+
}
|
|
1790
|
+
return `byteArrayOf(${Array.from(raw, (c) => `0x${c.charCodeAt(0).toString(16).padStart(2, "0")}`).join(", ")})`;
|
|
1791
|
+
}
|
|
1792
|
+
/** Render one wire AttributeValue as an `AttributeValue.…` constructor. */
|
|
1793
|
+
function renderKotlinAv(av) {
|
|
1794
|
+
if ("S" in av) return `AttributeValue.S(${ktString(av.S)})`;
|
|
1795
|
+
if ("N" in av) return `AttributeValue.N(${ktString(av.N)})`;
|
|
1796
|
+
if ("B" in av) return `AttributeValue.B(${ktBytes(av.B)})`;
|
|
1797
|
+
if ("BOOL" in av) return `AttributeValue.Bool(${av.BOOL})`;
|
|
1798
|
+
if ("SS" in av) return `AttributeValue.Ss(listOf(${av.SS.map(ktString).join(", ")}))`;
|
|
1799
|
+
if ("NS" in av) return `AttributeValue.Ns(listOf(${av.NS.map(ktString).join(", ")}))`;
|
|
1800
|
+
if ("BS" in av) return `AttributeValue.Bs(listOf(${av.BS.map(ktBytes).join(", ")}))`;
|
|
1801
|
+
return "AttributeValue.Null(true)";
|
|
1802
|
+
}
|
|
1803
|
+
/** Render a typed map as `mapOf("k" to AttributeValue.…)`, one entry per line. */
|
|
1804
|
+
function renderAvMap$1(map, indent) {
|
|
1805
|
+
const inner = `${indent} `;
|
|
1806
|
+
return `mapOf(\n${Object.entries(typedMapToAvMap(map)).map(([name, av]) => `${inner}${ktString(name)} to ${renderKotlinAv(av)},`).join("\n")}\n${indent})`;
|
|
1807
|
+
}
|
|
1808
|
+
/** Render the plain string map (`expressionAttributeNames`). */
|
|
1809
|
+
function renderNameMap$2(map, indent) {
|
|
1810
|
+
const inner = `${indent} `;
|
|
1811
|
+
return `mapOf(\n${Object.entries(map).map(([alias, name]) => `${inner}${ktString(alias)} to ${ktString(name)},`).join("\n")}\n${indent})`;
|
|
1812
|
+
}
|
|
1813
|
+
/**
|
|
1814
|
+
* Render the builder-lambda body — one property assignment per line at
|
|
1815
|
+
* `indent`. Exported for the program emitter, which wraps the same body in
|
|
1816
|
+
* either the plain suspend call or the `Paginated` flow variant.
|
|
1817
|
+
*/
|
|
1818
|
+
function renderKotlinBuilder(request, indent) {
|
|
1819
|
+
const lines = [`${indent}tableName = ${ktString(request.tableName)}`];
|
|
1820
|
+
if (request.indexName) lines.push(`${indent}indexName = ${ktString(request.indexName)}`);
|
|
1821
|
+
if (request.key) lines.push(`${indent}key = ${renderAvMap$1(request.key, indent)}`);
|
|
1822
|
+
if (request.item) lines.push(`${indent}item = ${renderAvMap$1(request.item, indent)}`);
|
|
1823
|
+
if (request.keyConditionExpression) lines.push(`${indent}keyConditionExpression = ${ktString(request.keyConditionExpression)}`);
|
|
1824
|
+
if (request.updateExpression) lines.push(`${indent}updateExpression = ${ktString(request.updateExpression)}`);
|
|
1825
|
+
if (request.conditionExpression) lines.push(`${indent}conditionExpression = ${ktString(request.conditionExpression)}`);
|
|
1826
|
+
if (request.filterExpression) lines.push(`${indent}filterExpression = ${ktString(request.filterExpression)}`);
|
|
1827
|
+
if (request.projectionExpression) lines.push(`${indent}projectionExpression = ${ktString(request.projectionExpression)}`);
|
|
1828
|
+
if (request.names) lines.push(`${indent}expressionAttributeNames = ${renderNameMap$2(request.names, indent)}`);
|
|
1829
|
+
if (request.typedValues) lines.push(`${indent}expressionAttributeValues = ${renderAvMap$1(request.typedValues, indent)}`);
|
|
1830
|
+
if (request.limit !== void 0) lines.push(`${indent}limit = ${request.limit}`);
|
|
1831
|
+
if (request.consistentRead) lines.push(`${indent}consistentRead = true`);
|
|
1832
|
+
if (request.scanIndexForward === false) lines.push(`${indent}scanIndexForward = false`);
|
|
1833
|
+
if (request.exclusiveStartKey) lines.push(`${indent}exclusiveStartKey = ${renderAvMap$1(request.exclusiveStartKey, indent)}`);
|
|
1834
|
+
return lines;
|
|
1835
|
+
}
|
|
1836
|
+
/** Emit the bare `val response = client.…{ … }` call for a canonical request. */
|
|
1837
|
+
function emitKotlin(request) {
|
|
1838
|
+
return [
|
|
1839
|
+
`val response = client.${CLIENT_METHOD_BY_OP$2[request.operation]} {`,
|
|
1840
|
+
...renderKotlinBuilder(request, " "),
|
|
1841
|
+
"}"
|
|
1842
|
+
].join("\n");
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
//#endregion
|
|
1846
|
+
//#region src/emit/php.ts
|
|
1847
|
+
/** Operation → the `DynamoDbClient` method. */
|
|
1848
|
+
const CLIENT_METHOD_BY_OP$1 = {
|
|
1849
|
+
GetItem: "getItem",
|
|
1850
|
+
Query: "query",
|
|
1851
|
+
Scan: "scan",
|
|
1852
|
+
Update: "updateItem",
|
|
1853
|
+
Put: "putItem",
|
|
1854
|
+
Delete: "deleteItem"
|
|
1855
|
+
};
|
|
1856
|
+
/** The client method name (camelCase) for an operation. */
|
|
1857
|
+
function phpClientMethodName(operation) {
|
|
1858
|
+
return CLIENT_METHOD_BY_OP$1[operation];
|
|
1859
|
+
}
|
|
1860
|
+
/** PHP single-quoted string — only `\` and `'` need escaping. */
|
|
1861
|
+
function phpString(value) {
|
|
1862
|
+
return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
1863
|
+
}
|
|
1864
|
+
/** Render one wire AttributeValue as a nested `['TAG' => …]` literal. */
|
|
1865
|
+
function renderPhpAv(av) {
|
|
1866
|
+
if ("S" in av) return `['S' => ${phpString(av.S)}]`;
|
|
1867
|
+
if ("N" in av) return `['N' => ${phpString(av.N)}]`;
|
|
1868
|
+
if ("B" in av) return `['B' => base64_decode(${phpString(av.B)})]`;
|
|
1869
|
+
if ("BOOL" in av) return `['BOOL' => ${av.BOOL}]`;
|
|
1870
|
+
if ("SS" in av) return `['SS' => [${av.SS.map(phpString).join(", ")}]]`;
|
|
1871
|
+
if ("NS" in av) return `['NS' => [${av.NS.map(phpString).join(", ")}]]`;
|
|
1872
|
+
if ("BS" in av) return `['BS' => [${av.BS.map((b) => `base64_decode(${phpString(b)})`).join(", ")}]]`;
|
|
1873
|
+
return "['NULL' => true]";
|
|
1874
|
+
}
|
|
1875
|
+
/** Render a typed map as a PHP array of AV literals, one entry per line. */
|
|
1876
|
+
function renderAvMap(map, indent) {
|
|
1877
|
+
const inner = `${indent} `;
|
|
1878
|
+
return `[\n${Object.entries(typedMapToAvMap(map)).map(([name, av]) => `${inner}${phpString(name)} => ${renderPhpAv(av)},`).join("\n")}\n${indent}]`;
|
|
1879
|
+
}
|
|
1880
|
+
/** Render the plain string map (`ExpressionAttributeNames`). */
|
|
1881
|
+
function renderNameMap$1(map, indent) {
|
|
1882
|
+
const inner = `${indent} `;
|
|
1883
|
+
return `[\n${Object.entries(map).map(([alias, name]) => `${inner}${phpString(alias)} => ${phpString(name)},`).join("\n")}\n${indent}]`;
|
|
1884
|
+
}
|
|
1885
|
+
/**
|
|
1886
|
+
* Render the request array literal, one field per line at `indent + 4`.
|
|
1887
|
+
* Exported for the program emitter.
|
|
1888
|
+
*/
|
|
1889
|
+
function renderPhpParams(request, indent) {
|
|
1890
|
+
const pad = `${indent} `;
|
|
1891
|
+
const fields = [`'TableName' => ${phpString(request.tableName)},`];
|
|
1892
|
+
if (request.indexName) fields.push(`'IndexName' => ${phpString(request.indexName)},`);
|
|
1893
|
+
if (request.key) fields.push(`'Key' => ${renderAvMap(request.key, pad)},`);
|
|
1894
|
+
if (request.item) fields.push(`'Item' => ${renderAvMap(request.item, pad)},`);
|
|
1895
|
+
if (request.keyConditionExpression) fields.push(`'KeyConditionExpression' => ${phpString(request.keyConditionExpression)},`);
|
|
1896
|
+
if (request.updateExpression) fields.push(`'UpdateExpression' => ${phpString(request.updateExpression)},`);
|
|
1897
|
+
if (request.conditionExpression) fields.push(`'ConditionExpression' => ${phpString(request.conditionExpression)},`);
|
|
1898
|
+
if (request.filterExpression) fields.push(`'FilterExpression' => ${phpString(request.filterExpression)},`);
|
|
1899
|
+
if (request.projectionExpression) fields.push(`'ProjectionExpression' => ${phpString(request.projectionExpression)},`);
|
|
1900
|
+
if (request.names) fields.push(`'ExpressionAttributeNames' => ${renderNameMap$1(request.names, pad)},`);
|
|
1901
|
+
if (request.typedValues) fields.push(`'ExpressionAttributeValues' => ${renderAvMap(request.typedValues, pad)},`);
|
|
1902
|
+
if (request.limit !== void 0) fields.push(`'Limit' => ${request.limit},`);
|
|
1903
|
+
if (request.consistentRead) fields.push("'ConsistentRead' => true,");
|
|
1904
|
+
if (request.scanIndexForward === false) fields.push("'ScanIndexForward' => false,");
|
|
1905
|
+
if (request.exclusiveStartKey) fields.push(`'ExclusiveStartKey' => ${renderAvMap(request.exclusiveStartKey, pad)},`);
|
|
1906
|
+
return [
|
|
1907
|
+
"[",
|
|
1908
|
+
...fields.map((f) => `${pad}${f}`),
|
|
1909
|
+
`${indent}]`
|
|
1910
|
+
].join("\n");
|
|
1911
|
+
}
|
|
1912
|
+
/** Emit the bare `$response = $client->…([…]);` call for a canonical request. */
|
|
1913
|
+
function emitPhp(request) {
|
|
1914
|
+
return `$response = $client->${CLIENT_METHOD_BY_OP$1[request.operation]}(${renderPhpParams(request, "")});`;
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
//#endregion
|
|
1918
|
+
//#region src/emit/ruby.ts
|
|
1919
|
+
/** Operation → the `Aws::DynamoDB::Client` method (snake_case). */
|
|
1920
|
+
const CLIENT_METHOD_BY_OP = {
|
|
1921
|
+
GetItem: "get_item",
|
|
1922
|
+
Query: "query",
|
|
1923
|
+
Scan: "scan",
|
|
1924
|
+
Update: "update_item",
|
|
1925
|
+
Put: "put_item",
|
|
1926
|
+
Delete: "delete_item"
|
|
1927
|
+
};
|
|
1928
|
+
/** The client method name (snake_case) for an operation. */
|
|
1929
|
+
function rubyClientMethodName(operation) {
|
|
1930
|
+
return CLIENT_METHOD_BY_OP[operation];
|
|
1931
|
+
}
|
|
1932
|
+
/** Ruby single-quoted string — only `\` and `'` need escaping. */
|
|
1933
|
+
function rubyString(value) {
|
|
1934
|
+
return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
1935
|
+
}
|
|
1936
|
+
/** Render one typed value as the native Ruby literal the SDK marshals. */
|
|
1937
|
+
function renderRubyValue(tv) {
|
|
1938
|
+
switch (tv.type) {
|
|
1939
|
+
case "S": return rubyString(tv.value);
|
|
1940
|
+
case "N": return tv.value;
|
|
1941
|
+
case "B": return `Base64.decode64(${rubyString(tv.value)})`;
|
|
1942
|
+
case "BOOL": return tv.value === "true" ? "true" : "false";
|
|
1943
|
+
case "NULL": return "nil";
|
|
1944
|
+
case "SS": return `Set.new([${(tv.values ?? []).map(rubyString).join(", ")}])`;
|
|
1945
|
+
case "NS": return `Set.new([${(tv.values ?? []).join(", ")}])`;
|
|
1946
|
+
case "BS": return `Set.new([${(tv.values ?? []).map((b) => `Base64.decode64(${rubyString(b)})`).join(", ")}])`;
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
/** Render a typed map as a Ruby hash of native values, one entry per line. */
|
|
1950
|
+
function renderValueMap(map, indent) {
|
|
1951
|
+
const inner = `${indent} `;
|
|
1952
|
+
return `{\n${Object.entries(map).map(([name, tv]) => `${inner}${rubyString(name)} => ${renderRubyValue(tv)},`).join("\n")}\n${indent}}`;
|
|
1953
|
+
}
|
|
1954
|
+
/** Render the plain string map (`expression_attribute_names`). */
|
|
1955
|
+
function renderNameMap(map, indent) {
|
|
1956
|
+
const inner = `${indent} `;
|
|
1957
|
+
return `{\n${Object.entries(map).map(([alias, name]) => `${inner}${rubyString(alias)} => ${rubyString(name)},`).join("\n")}\n${indent}}`;
|
|
1958
|
+
}
|
|
1959
|
+
/**
|
|
1960
|
+
* Render the request keyword-argument hash, one field per line at `indent + 2`.
|
|
1961
|
+
* Exported for the program emitter.
|
|
1962
|
+
*/
|
|
1963
|
+
function renderRubyParams(request, indent) {
|
|
1964
|
+
const pad = `${indent} `;
|
|
1965
|
+
const fields = [`table_name: ${rubyString(request.tableName)},`];
|
|
1966
|
+
if (request.indexName) fields.push(`index_name: ${rubyString(request.indexName)},`);
|
|
1967
|
+
if (request.key) fields.push(`key: ${renderValueMap(request.key, pad)},`);
|
|
1968
|
+
if (request.item) fields.push(`item: ${renderValueMap(request.item, pad)},`);
|
|
1969
|
+
if (request.keyConditionExpression) fields.push(`key_condition_expression: ${rubyString(request.keyConditionExpression)},`);
|
|
1970
|
+
if (request.updateExpression) fields.push(`update_expression: ${rubyString(request.updateExpression)},`);
|
|
1971
|
+
if (request.conditionExpression) fields.push(`condition_expression: ${rubyString(request.conditionExpression)},`);
|
|
1972
|
+
if (request.filterExpression) fields.push(`filter_expression: ${rubyString(request.filterExpression)},`);
|
|
1973
|
+
if (request.projectionExpression) fields.push(`projection_expression: ${rubyString(request.projectionExpression)},`);
|
|
1974
|
+
if (request.names) fields.push(`expression_attribute_names: ${renderNameMap(request.names, pad)},`);
|
|
1975
|
+
if (request.typedValues) fields.push(`expression_attribute_values: ${renderValueMap(request.typedValues, pad)},`);
|
|
1976
|
+
if (request.limit !== void 0) fields.push(`limit: ${request.limit},`);
|
|
1977
|
+
if (request.consistentRead) fields.push("consistent_read: true,");
|
|
1978
|
+
if (request.scanIndexForward === false) fields.push("scan_index_forward: false,");
|
|
1979
|
+
if (request.exclusiveStartKey) fields.push(`exclusive_start_key: ${renderValueMap(request.exclusiveStartKey, pad)},`);
|
|
1980
|
+
return [
|
|
1981
|
+
"{",
|
|
1982
|
+
...fields.map((f) => `${pad}${f}`),
|
|
1983
|
+
`${indent}}`
|
|
1984
|
+
].join("\n");
|
|
1985
|
+
}
|
|
1986
|
+
/** Emit the bare `response = client.…(…)` call for a canonical request. */
|
|
1987
|
+
function emitRuby(request) {
|
|
1988
|
+
return `response = client.${CLIENT_METHOD_BY_OP[request.operation]}(${renderRubyParams(request, "")})`;
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1586
1991
|
//#endregion
|
|
1587
1992
|
//#region src/program.ts
|
|
1588
1993
|
/**
|
|
@@ -1627,6 +2032,26 @@ function emitQueryProgram(config, format) {
|
|
|
1627
2032
|
ok: true,
|
|
1628
2033
|
code: emitDotnetProgram(request, config.paginate === true)
|
|
1629
2034
|
};
|
|
2035
|
+
case "rust": return {
|
|
2036
|
+
ok: true,
|
|
2037
|
+
code: emitRustProgram(request, config.paginate === true)
|
|
2038
|
+
};
|
|
2039
|
+
case "docclient": return {
|
|
2040
|
+
ok: true,
|
|
2041
|
+
code: emitDocClientProgram(request, config.paginate === true)
|
|
2042
|
+
};
|
|
2043
|
+
case "kotlin": return {
|
|
2044
|
+
ok: true,
|
|
2045
|
+
code: emitKotlinProgram(request, config.paginate === true)
|
|
2046
|
+
};
|
|
2047
|
+
case "php": return {
|
|
2048
|
+
ok: true,
|
|
2049
|
+
code: emitPhpProgram(request, config.paginate === true)
|
|
2050
|
+
};
|
|
2051
|
+
case "ruby": return {
|
|
2052
|
+
ok: true,
|
|
2053
|
+
code: emitRubyProgram(request, config.paginate === true)
|
|
2054
|
+
};
|
|
1630
2055
|
case "ddbtoolbox": return {
|
|
1631
2056
|
ok: true,
|
|
1632
2057
|
code: emitDdbToolboxProgram(request, config.paginate === true)
|
|
@@ -1824,6 +2249,173 @@ function emitGoProgram(request, paginate) {
|
|
|
1824
2249
|
"}"
|
|
1825
2250
|
].join("\n");
|
|
1826
2251
|
}
|
|
2252
|
+
function emitRustProgram(request, paginate) {
|
|
2253
|
+
const usesAv = rustUsesAttributeValue(request);
|
|
2254
|
+
const usesBlob = rustUsesBlob(request);
|
|
2255
|
+
const header = [
|
|
2256
|
+
...[
|
|
2257
|
+
"// Cargo.toml: aws-config, aws-sdk-dynamodb, tokio (features = [\"full\"])",
|
|
2258
|
+
"use aws_sdk_dynamodb::Client;",
|
|
2259
|
+
...usesAv ? ["use aws_sdk_dynamodb::types::AttributeValue;"] : [],
|
|
2260
|
+
...usesBlob ? ["use aws_sdk_dynamodb::primitives::Blob;"] : []
|
|
2261
|
+
],
|
|
2262
|
+
"",
|
|
2263
|
+
"#[tokio::main]",
|
|
2264
|
+
"async fn main() -> Result<(), aws_sdk_dynamodb::Error> {",
|
|
2265
|
+
" let config = aws_config::load_from_env().await;",
|
|
2266
|
+
" let client = Client::new(&config);",
|
|
2267
|
+
""
|
|
2268
|
+
];
|
|
2269
|
+
const builder = renderRustBuilder(request, " ");
|
|
2270
|
+
if (!paginate) return [
|
|
2271
|
+
...header,
|
|
2272
|
+
" let response = client",
|
|
2273
|
+
...builder,
|
|
2274
|
+
" .send()",
|
|
2275
|
+
" .await?;",
|
|
2276
|
+
" println!(\"{:?}\", response.items());",
|
|
2277
|
+
"",
|
|
2278
|
+
" Ok(())",
|
|
2279
|
+
"}"
|
|
2280
|
+
].join("\n");
|
|
2281
|
+
return [
|
|
2282
|
+
...header,
|
|
2283
|
+
" let mut items = client",
|
|
2284
|
+
...builder,
|
|
2285
|
+
" .into_paginator()",
|
|
2286
|
+
" .items()",
|
|
2287
|
+
" .send();",
|
|
2288
|
+
"",
|
|
2289
|
+
" while let Some(item) = items.next().await {",
|
|
2290
|
+
" println!(\"{:?}\", item?);",
|
|
2291
|
+
" }",
|
|
2292
|
+
"",
|
|
2293
|
+
" Ok(())",
|
|
2294
|
+
"}"
|
|
2295
|
+
].join("\n");
|
|
2296
|
+
}
|
|
2297
|
+
function emitDocClientProgram(request, paginate) {
|
|
2298
|
+
const command = docClientCommandName(request.operation);
|
|
2299
|
+
renderDocClientParams(request, "");
|
|
2300
|
+
if (!paginate) return [
|
|
2301
|
+
"import { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";",
|
|
2302
|
+
`import { DynamoDBDocumentClient, ${command} } from "@aws-sdk/lib-dynamodb";`,
|
|
2303
|
+
"",
|
|
2304
|
+
"const client = DynamoDBDocumentClient.from(new DynamoDBClient({}));",
|
|
2305
|
+
"",
|
|
2306
|
+
"const response = await client.send(",
|
|
2307
|
+
` new ${command}(${renderDocClientParams(request, " ")})`,
|
|
2308
|
+
");",
|
|
2309
|
+
"",
|
|
2310
|
+
"console.log(response.Items);"
|
|
2311
|
+
].join("\n");
|
|
2312
|
+
const paginator = request.operation === "Scan" ? "paginateScan" : "paginateQuery";
|
|
2313
|
+
return [
|
|
2314
|
+
"import { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";",
|
|
2315
|
+
`import { DynamoDBDocumentClient, ${paginator} } from "@aws-sdk/lib-dynamodb";`,
|
|
2316
|
+
"",
|
|
2317
|
+
"const client = DynamoDBDocumentClient.from(new DynamoDBClient({}));",
|
|
2318
|
+
"",
|
|
2319
|
+
`const paginator = ${paginator}(`,
|
|
2320
|
+
" { client },",
|
|
2321
|
+
` ${renderDocClientParams(request, " ")}`,
|
|
2322
|
+
");",
|
|
2323
|
+
"",
|
|
2324
|
+
"for await (const page of paginator) {",
|
|
2325
|
+
" console.log(page.Items);",
|
|
2326
|
+
"}"
|
|
2327
|
+
].join("\n");
|
|
2328
|
+
}
|
|
2329
|
+
function emitKotlinProgram(request, paginate) {
|
|
2330
|
+
const method = kotlinClientMethodName(request.operation);
|
|
2331
|
+
const header = [
|
|
2332
|
+
"import aws.sdk.kotlin.services.dynamodb.DynamoDbClient",
|
|
2333
|
+
"import aws.sdk.kotlin.services.dynamodb.model.AttributeValue",
|
|
2334
|
+
...paginate ? [
|
|
2335
|
+
`import aws.sdk.kotlin.services.dynamodb.paginators.${method}Paginated`,
|
|
2336
|
+
"import aws.sdk.kotlin.services.dynamodb.paginators.items",
|
|
2337
|
+
"import kotlinx.coroutines.flow.collect"
|
|
2338
|
+
] : [],
|
|
2339
|
+
"",
|
|
2340
|
+
"suspend fun main() {",
|
|
2341
|
+
" DynamoDbClient.fromEnvironment().use { client ->"
|
|
2342
|
+
];
|
|
2343
|
+
const body = renderKotlinBuilder(request, " ");
|
|
2344
|
+
if (!paginate) return [
|
|
2345
|
+
...header,
|
|
2346
|
+
` val response = client.${method} {`,
|
|
2347
|
+
...body,
|
|
2348
|
+
" }",
|
|
2349
|
+
" println(response.items)",
|
|
2350
|
+
" }",
|
|
2351
|
+
"}"
|
|
2352
|
+
].join("\n");
|
|
2353
|
+
return [
|
|
2354
|
+
...header,
|
|
2355
|
+
` client.${method}Paginated {`,
|
|
2356
|
+
...body,
|
|
2357
|
+
" }",
|
|
2358
|
+
" .items()",
|
|
2359
|
+
" .collect { item -> println(item) }",
|
|
2360
|
+
" }",
|
|
2361
|
+
"}"
|
|
2362
|
+
].join("\n");
|
|
2363
|
+
}
|
|
2364
|
+
function emitPhpProgram(request, paginate) {
|
|
2365
|
+
const method = phpClientMethodName(request.operation);
|
|
2366
|
+
const header = [
|
|
2367
|
+
"<?php",
|
|
2368
|
+
"",
|
|
2369
|
+
"require 'vendor/autoload.php';",
|
|
2370
|
+
"",
|
|
2371
|
+
"use Aws\\DynamoDb\\DynamoDbClient;",
|
|
2372
|
+
"",
|
|
2373
|
+
"$client = new DynamoDbClient(['region' => 'us-east-1', 'version' => 'latest']);",
|
|
2374
|
+
""
|
|
2375
|
+
];
|
|
2376
|
+
if (!paginate) return [
|
|
2377
|
+
...header,
|
|
2378
|
+
`$response = $client->${method}(${renderPhpParams(request, "")});`,
|
|
2379
|
+
"",
|
|
2380
|
+
"print_r($response['Items']);"
|
|
2381
|
+
].join("\n");
|
|
2382
|
+
const operation = request.operation === "Scan" ? "Scan" : "Query";
|
|
2383
|
+
return [
|
|
2384
|
+
...header,
|
|
2385
|
+
`$pages = $client->getPaginator('${operation}', ${renderPhpParams(request, "")});`,
|
|
2386
|
+
"",
|
|
2387
|
+
"foreach ($pages as $page) {",
|
|
2388
|
+
" print_r($page['Items']);",
|
|
2389
|
+
"}"
|
|
2390
|
+
].join("\n");
|
|
2391
|
+
}
|
|
2392
|
+
function emitRubyProgram(request, paginate) {
|
|
2393
|
+
const method = rubyClientMethodName(request.operation);
|
|
2394
|
+
const usesSets = /Set\.new\(/.test(renderRubyParams(request, ""));
|
|
2395
|
+
const usesBase64 = /Base64\.decode64\(/.test(renderRubyParams(request, ""));
|
|
2396
|
+
const header = [
|
|
2397
|
+
"require 'aws-sdk-dynamodb'",
|
|
2398
|
+
...usesSets ? ["require 'set'"] : [],
|
|
2399
|
+
...usesBase64 ? ["require 'base64'"] : [],
|
|
2400
|
+
"",
|
|
2401
|
+
"client = Aws::DynamoDB::Client.new",
|
|
2402
|
+
""
|
|
2403
|
+
];
|
|
2404
|
+
if (!paginate) return [
|
|
2405
|
+
...header,
|
|
2406
|
+
`response = client.${method}(${renderRubyParams(request, "")})`,
|
|
2407
|
+
"",
|
|
2408
|
+
"puts response.items"
|
|
2409
|
+
].join("\n");
|
|
2410
|
+
return [
|
|
2411
|
+
...header,
|
|
2412
|
+
`response = client.${method}(${renderRubyParams(request, "")})`,
|
|
2413
|
+
"",
|
|
2414
|
+
"response.each do |page|",
|
|
2415
|
+
" puts page.items",
|
|
2416
|
+
"end"
|
|
2417
|
+
].join("\n");
|
|
2418
|
+
}
|
|
1827
2419
|
function emitDotnetProgram(request, paginate) {
|
|
1828
2420
|
const method = dotnetClientMethodName(request.operation);
|
|
1829
2421
|
const binary = hasBinaryValue(request);
|
|
@@ -1880,17 +2472,23 @@ exports.buildKeyMap = buildKeyMap;
|
|
|
1880
2472
|
exports.buildRequest = buildRequest;
|
|
1881
2473
|
exports.buildSdkV3Params = buildSdkV3Params;
|
|
1882
2474
|
exports.buildUpdateExpression = buildUpdateExpression;
|
|
2475
|
+
exports.docClientCommandName = docClientCommandName;
|
|
1883
2476
|
exports.dotnetClientMethodName = dotnetClientMethodName;
|
|
1884
2477
|
exports.dotnetRequestClassName = dotnetRequestClassName;
|
|
1885
2478
|
exports.elementType = elementType;
|
|
1886
2479
|
exports.emitBoto3 = emitBoto3;
|
|
1887
2480
|
exports.emitCli = emitCli;
|
|
1888
2481
|
exports.emitDdbToolboxProgram = emitDdbToolboxProgram;
|
|
2482
|
+
exports.emitDocClient = emitDocClient;
|
|
1889
2483
|
exports.emitDotnet = emitDotnet;
|
|
1890
2484
|
exports.emitGo = emitGo;
|
|
1891
2485
|
exports.emitJava = emitJava;
|
|
2486
|
+
exports.emitKotlin = emitKotlin;
|
|
1892
2487
|
exports.emitPartiql = emitPartiql;
|
|
2488
|
+
exports.emitPhp = emitPhp;
|
|
1893
2489
|
exports.emitQueryProgram = emitQueryProgram;
|
|
2490
|
+
exports.emitRuby = emitRuby;
|
|
2491
|
+
exports.emitRust = emitRust;
|
|
1894
2492
|
exports.emitSdkV3 = emitSdkV3;
|
|
1895
2493
|
exports.getCompatibleComparisonOperators = getCompatibleComparisonOperators;
|
|
1896
2494
|
exports.getCompatibleFilterOperators = getCompatibleFilterOperators;
|
|
@@ -1900,9 +2498,17 @@ exports.hasBinaryValue = hasBinaryValue;
|
|
|
1900
2498
|
exports.isSetType = isSetType;
|
|
1901
2499
|
exports.javaClientMethodName = javaClientMethodName;
|
|
1902
2500
|
exports.javaRequestClassName = javaRequestClassName;
|
|
2501
|
+
exports.kotlinClientMethodName = kotlinClientMethodName;
|
|
1903
2502
|
exports.makeTypedValue = makeTypedValue;
|
|
2503
|
+
exports.phpClientMethodName = phpClientMethodName;
|
|
1904
2504
|
exports.renderJsValue = renderJsValue;
|
|
2505
|
+
exports.renderKotlinAv = renderKotlinAv;
|
|
2506
|
+
exports.renderPhpAv = renderPhpAv;
|
|
1905
2507
|
exports.renderPyValue = renderPyValue;
|
|
2508
|
+
exports.renderRubyValue = renderRubyValue;
|
|
2509
|
+
exports.renderRustAv = renderRustAv;
|
|
2510
|
+
exports.rubyClientMethodName = rubyClientMethodName;
|
|
2511
|
+
exports.rustClientMethodName = rustClientMethodName;
|
|
1906
2512
|
exports.sdkV3CommandName = sdkV3CommandName;
|
|
1907
2513
|
exports.typedMapToAvMap = typedMapToAvMap;
|
|
1908
2514
|
exports.typedValueToAv = typedValueToAv;
|