Skip to content

Commit e026e10

Browse files
authored
Add v0.5 codegen with last surviving aws-sdk-js v2 (#56)
* Add v0.5 with last surviving aws-sdk-js v2 * Add new fields to ApiMetadata * Implement request header 'lists' Uses header.append() so this effectively joins by comma if there are multiple items in a request header array. * Implement list of integers in rest input query * Escape json input keys when they aren't alphanumeric * Replace canary in CI with 2.3 * What about deno 2.2 as latest supported * Move base64 import to JSR to get Uint8Array fix * Also switch md5 lib to a JSR one * Drop support for Deno v1 * Drop deno 2.5 for now, has typescript issue * Fix version exclusion
1 parent 95cbc5d commit e026e10

33 files changed

Lines changed: 5815 additions & 458 deletions

.github/workflows/deno-ci.yml

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,11 @@ jobs:
1414
fail-fast: false
1515
matrix:
1616
deno-version:
17-
- v1.22
18-
- v1.24
19-
- v1.26
20-
- v1.28
21-
- v1.30
22-
- v1.35
23-
- v1.40
24-
- v1.45
2517
- v2.0
26-
- canary
18+
- v2.1
19+
- v2.2
20+
- v2.3
21+
- v2.4
2722

2823
steps:
2924
- name: Checkout source
@@ -69,8 +64,10 @@ jobs:
6964
fail-fast: false
7065
matrix:
7166
deno-version:
72-
- v2.0
73-
- canary
67+
- v2.1
68+
- v2.2
69+
- v2.3
70+
- v2.4
7471

7572
steps:
7673
- name: Checkout source
@@ -101,11 +98,11 @@ jobs:
10198
strategy:
10299
matrix:
103100
deno-version:
104-
- v1.35
105-
- v1.40
106-
- v1.45
107101
- v2.0
108-
- canary
102+
- v2.1
103+
- v2.2
104+
- v2.3
105+
- v2.4
109106
fail-fast: false # run each branch to completion
110107

111108
steps:
@@ -146,7 +143,7 @@ jobs:
146143
strategy:
147144
matrix:
148145
deno-version:
149-
- v2.0
146+
- v2.4
150147

151148
steps:
152149
- name: Checkout source

aws-sdk-js

Submodule aws-sdk-js updated 2329 files

generation/code-gen.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export default class ServiceCodeGen {
2121
useAuthType: boolean; // for aws-api v0.6.0
2222
alwaysReqLists: boolean; // for codegen v0.2 and earlier
2323
streamingResponses: boolean; // for codegen v0.3 and earlier
24+
useStdJsr: boolean;
2425
shapes: ShapeLibrary;
2526

2627
constructor(specs: {
@@ -48,6 +49,7 @@ export default class ServiceCodeGen {
4849
this.useAuthType = (opts.get('useAuthType') || 'yes') !== 'no';
4950
this.alwaysReqLists = (opts.get('alwaysReqLists') || 'no') !== 'no';
5051
this.streamingResponses = (opts.get('streamingResponses') || 'yes') !== 'no';
52+
this.useStdJsr = (opts.get('useStdJsr') || 'yes') !== 'no';
5153

5254
// mutate the specs to fix inaccuracies
5355
fixupApiSpec(this.apiSpec);
@@ -59,7 +61,10 @@ export default class ServiceCodeGen {
5961
}
6062

6163
generateTypescript(namespace: string): string {
62-
const helpers = makeHelperLibrary({ isTest: this.isTest });
64+
const helpers = makeHelperLibrary({
65+
isTest: this.isTest,
66+
useStdJsr: this.useStdJsr,
67+
});
6368
const protocol = makeProtocolCodegenFor(this.apiSpec.metadata, this.shapes, helpers, {
6469
includeJsonRemap: this.includeJsonRemap,
6570
});
@@ -95,7 +100,10 @@ export default class ServiceCodeGen {
95100
}
96101

97102
generateModTypescript(namespace: string): string {
98-
const helpers = makeHelperLibrary({ isTest: this.isTest });
103+
const helpers = makeHelperLibrary({
104+
isTest: this.isTest,
105+
useStdJsr: this.useStdJsr,
106+
});
99107
const protocol = makeProtocolCodegenFor(this.apiSpec.metadata, this.shapes, helpers, {
100108
includeJsonRemap: this.includeJsonRemap,
101109
});
@@ -129,7 +137,10 @@ export default class ServiceCodeGen {
129137
}
130138

131139
generateStructsTypescript(): string {
132-
const helpers = makeHelperLibrary({ isTest: this.isTest });
140+
const helpers = makeHelperLibrary({
141+
isTest: this.isTest,
142+
useStdJsr: this.useStdJsr,
143+
});
133144
const protocol = makeProtocolCodegenFor(this.apiSpec.metadata, this.shapes, helpers, {
134145
includeJsonRemap: this.includeJsonRemap,
135146
});

generation/deploy/generations.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export const Generations = new Map<string, ModuleGenerator>([
5555
'v2.895.0',
5656
new URLSearchParams([
5757
['aws_api_root', 'https://deno.land/x/aws_api@v0.4.0'],
58+
['useStdJsr', 'no'],
5859
['includeOpts', 'no'],
5960
['includeJsonRemap', 'no'],
6061
['includeClientExtras', 'no'],
@@ -70,6 +71,7 @@ export const Generations = new Map<string, ModuleGenerator>([
7071
'v2.971.0',
7172
new URLSearchParams([
7273
['aws_api_root', 'https://deno.land/x/aws_api@v0.5.0'],
74+
['useStdJsr', 'no'],
7375
['includeJsonRemap', 'no'],
7476
['includeClientExtras', 'no'],
7577
['useAuthType', 'no'],
@@ -84,6 +86,7 @@ export const Generations = new Map<string, ModuleGenerator>([
8486
'v2.1060.0',
8587
new URLSearchParams([
8688
['aws_api_root', 'https://deno.land/x/aws_api@v0.6.0'],
89+
['useStdJsr', 'no'],
8790
['streamingResponses', 'no'],
8891
['docs', 'short'],
8992
]),
@@ -92,11 +95,21 @@ export const Generations = new Map<string, ModuleGenerator>([
9295
['v0.4', new ModuleGenerator(
9396
'https://deno.land/std@0.177.0',
9497
'v2.1323.0', // https://github.com/aws/aws-sdk-js/releases
98+
new URLSearchParams([
99+
['aws_api_root', 'https://deno.land/x/aws_api@v0.8.1'],
100+
['useStdJsr', 'no'],
101+
['docs', 'short'],
102+
]),
103+
(config, opts) => new LatestCodeGen(config, opts),
104+
)],
105+
['v0.5', new ModuleGenerator(
106+
'https://deno.land/std@0.177.0',
107+
'v2.1692.0', // https://github.com/aws/aws-sdk-js/releases
95108
new URLSearchParams([
96109
['aws_api_root', 'https://deno.land/x/aws_api@v0.8.1'],
97110
['docs', 'short'],
98111
]),
99112
(config, opts) => new LatestCodeGen(config, opts),
100113
)],
101114
]);
102-
export const LatestGeneration = 'v0.4';
115+
export const LatestGeneration = 'v0.5';

generation/helper-library.ts

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,19 @@ export const HashMD5: Helper = {
8282
],
8383
};
8484

85+
export const HashMD5JSR: Helper = {
86+
deps: {
87+
HashMd5: "jsr:@takker/md5@0.1.0",
88+
Base64: "jsr:@std/encoding@1.0.10/base64",
89+
},
90+
chunks: [
91+
`function hashMD5(data: BufferSource | string): string {`,
92+
` const hashed = HashMd5.md5(data);`,
93+
` return Base64.encodeBase64(hashed);`,
94+
`}`,
95+
],
96+
};
97+
8598
export const SerializeBlob: Helper = {
8699
deps: {
87100
Base64: "https://deno.land/std@0.177.0/encoding/base64.ts",
@@ -105,6 +118,29 @@ export const ParseBlob: Helper = {
105118
],
106119
};
107120

121+
export const SerializeBlobJSR: Helper = {
122+
deps: {
123+
Base64: "jsr:@std/encoding@1.0.10/base64",
124+
},
125+
chunks: [
126+
`function serializeBlob(input: string | Uint8Array | null | undefined) {`,
127+
` if (input == null) return input;`,
128+
` return Base64.encodeBase64(input);`,
129+
`}`,
130+
],
131+
};
132+
export const ParseBlobJSR: Helper = {
133+
deps: {
134+
Base64: "jsr:@std/encoding@1.0.10/base64",
135+
},
136+
chunks: [
137+
`function parseBlob(input: string | null | undefined) {`,
138+
` if (input == null) return input;`,
139+
` return Base64.decodeBase64(input);`,
140+
`}`,
141+
],
142+
};
143+
108144
export const IdemptToken: Helper = {
109145
chunks: [
110146
`function generateIdemptToken() {`,
@@ -121,8 +157,9 @@ export const IdemptTokenMock: Helper = {
121157
};
122158

123159
export function makeHelperLibrary(opts: {
124-
isTest?: boolean;
125-
} = {}) {
160+
isTest: boolean;
161+
useStdJsr: boolean;
162+
}) {
126163
const lib = new HelperLibrary();
127164

128165
// lib.addOptionalDep('Base64', 'https://deno.land/x/base64@v0.2.1/mod.ts');
@@ -137,10 +174,17 @@ export function makeHelperLibrary(opts: {
137174
? IdemptTokenMock
138175
: IdemptToken);
139176

140-
lib.addHelper('hashMD5', HashMD5);
177+
if (opts.useStdJsr) {
178+
lib.addHelper('hashMD5', HashMD5JSR);
179+
180+
lib.addHelper('serializeBlob', SerializeBlobJSR);
181+
lib.addHelper('parseBlob', ParseBlobJSR);
182+
} else {
183+
lib.addHelper('hashMD5', HashMD5);
141184

142-
lib.addHelper('serializeBlob', SerializeBlob);
143-
lib.addHelper('parseBlob', ParseBlob);
185+
lib.addHelper('serializeBlob', SerializeBlob);
186+
lib.addHelper('parseBlob', ParseBlob);
187+
}
144188

145189
return lib;
146190
}

generation/protocol-json.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,18 @@ export default class ProtocolJsonCodegen {
103103
encoder = `${fieldRef} ?? generateIdemptToken()`;
104104
}
105105

106+
const locationRef = locationName.match(/^[a-z0-9]+$/i) ? locationName : `${JSON.stringify(locationName)}`;
106107
if (encoder) {
107108
if (isList) {
108-
chunks.push(` ${locationName}: ${rootRef}[${JSON.stringify(field)}]?.map(x => ${encoder}),`);
109+
chunks.push(` ${locationRef}: ${rootRef}[${JSON.stringify(field)}]?.map(x => ${encoder}),`);
109110
} else if (isMap) {
110111
this.helpers.useHelper("jsonP");
111-
chunks.push(` ${locationName}: jsonP.serializeMap(${rootRef}[${JSON.stringify(field)}], x => ${encoder}),`);
112+
chunks.push(` ${locationRef}: jsonP.serializeMap(${rootRef}[${JSON.stringify(field)}], x => ${encoder}),`);
112113
} else {
113-
chunks.push(` ${locationName}: ${encoder},`);
114+
chunks.push(` ${locationRef}: ${encoder},`);
114115
}
115116
} else {
116-
chunks.push(` ${locationName}: ${rootRef}[${JSON.stringify(field)}],`);
117+
chunks.push(` ${locationRef}: ${rootRef}[${JSON.stringify(field)}],`);
117118
}
118119
}
119120
chunks.push(` }`);
@@ -317,7 +318,8 @@ export default class ProtocolJsonCodegen {
317318
if (valShape.tags.has('named')) {
318319
// TODO: is this safe? when would an array have a null?
319320
expr = `y => jsonP.readList(to${valShape.censoredName}, y)!`;
320-
} else if (['long', 'integer'].includes(valShape.spec.type)) {
321+
} else if (valShape.isNumberType) {
322+
// TODO: consider a separate readInt
321323
expr = `y => jsonP.readList(jsonP.readNum, y)!`;
322324
} else throw new Error(`TODO: json output list ${valShape.spec.type}`);
323325
}

generation/protocol-rest.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,11 @@ export default class ProtocolRestCodegen {
6767
}
6868
break;
6969
case 'header':
70-
let formattedRef = paramRef; // + ' ?? null';
71-
switch (shape.spec.type) {
70+
let formattedRef = shape.spec.type == 'list' ? 'item' : paramRef;
71+
const headerShape = shape.spec.type == 'list' ? this.shapes.get(shape.spec.member) : shape;
72+
switch (headerShape.spec.type) {
7273
case 'timestamp': {
73-
const format = spec.timestampFormat ?? shape.spec.timestampFormat ?? 'rfc822';
74+
const format = spec.timestampFormat ?? headerShape.spec.timestampFormat ?? 'rfc822';
7475
formattedRef = `cmnP.serializeDate_${format}(${formattedRef})${format === 'unixTimestamp' ? '?.toString()' : ''} ?? ""`;
7576
this.helpers.useHelper("cmnP");
7677
break;
@@ -98,8 +99,16 @@ export default class ProtocolRestCodegen {
9899
break;
99100
}
100101
break;
102+
default:
103+
throw new Error(`TODO: unhandled input header list type ${headerShape.spec.type}`);
101104
}
102-
chunks.push(` ${isRequired ? '' : `if (${paramRef} != null) `}headers.append(${JSON.stringify(/*spec.queryName ?? */locationName)}, ${formattedRef});`);
105+
if (shape.spec.type == 'list') {
106+
chunks.push(` for (const item of ${paramRef} ?? []) {`);
107+
chunks.push(` query.append(${JSON.stringify(locationName)}, ${formattedRef});`);
108+
chunks.push(` }`);
109+
} else {
110+
chunks.push(` ${isRequired ? '' : `if (${paramRef} != null) `}headers.append(${JSON.stringify(locationName)}, ${formattedRef});`);
111+
}
103112
break;
104113
case 'headers': {
105114
if (shape.spec.type !== 'map') throw new Error(`rest input headers not map`);
@@ -142,6 +151,7 @@ export default class ProtocolRestCodegen {
142151
const inner = this.shapes.get(shape.spec.member);
143152
switch (inner.spec.type) {
144153
case 'string':
154+
case 'integer':
145155
chunks.push(` for (const item of ${paramRef}${isRequired ? '' : ' ?? []'}) {`);
146156
chunks.push(` query.append(${JSON.stringify(spec.queryName ?? locationName)}, item?.toString() ?? "");`);
147157
chunks.push(` }`);

lib/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ Multiple bits are *missing*:
262262

263263
[//]: # (Generated Content Barrier)
264264

265-
All API definitions are current as of [aws-sdk-js `v2.1060.0`](https://github.com/aws/aws-sdk-js/releases/tag/v2.1060.0).
265+
All API definitions are current as of [aws-sdk-js `v2.1692.0`](https://github.com/aws/aws-sdk-js/releases/tag/v2.1692.0).
266266

267267
| Class | Module | Protocol |
268268
| --- | --- | --- |

lib/client/common.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,14 @@ export interface ServiceClientExtras {
9494
// our understanding of how APIs can describe themselves
9595
export interface ApiMetadata {
9696
"apiVersion": string;
97+
"auth"?: Array<"aws.auth#sigv4">;
98+
"awsQueryCompatible"?: unknown; // seems to be bool-ish with `{}` as truthy value
9799
"checksumFormat"?: "md5" | "sha256";
98100
"endpointPrefix": string;
99101
"jsonVersion"?: "1.0" | "1.1",
100102
"globalEndpoint"?: string;
101103
"protocol": "rest-xml" | "query" | "ec2" | "json" | "rest-json";
104+
"protocols"?: Array<"rest-xml" | "query" | "ec2" | "json" | "rest-json">;
102105
"protocolSettings"?: {
103106
"h2": "eventstream"; // only for kinesis
104107
};

0 commit comments

Comments
 (0)