Skip to content

Commit 9e11e5d

Browse files
authored
correctly handle stack argument for generate schema command (#2028)
* correctly handle stack argument for generate schema command * PR feedback * update type * add await * update resolver methods
1 parent f33ff6b commit 9e11e5d

11 files changed

+181
-59
lines changed

.changeset/fluffy-months-prove.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@aws-amplify/backend-cli': patch
3+
---
4+
5+
correctly handle stack argument for generate schema command

packages/cli/src/backend-identifier/backend_identifier_resolver.test.ts

Lines changed: 71 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,82 @@ import { describe, it } from 'node:test';
33
import { AppBackendIdentifierResolver } from './backend_identifier_resolver.js';
44

55
void describe('BackendIdentifierResolver', () => {
6-
void it('returns an App Name and Branch identifier', async () => {
7-
const backendIdResolver = new AppBackendIdentifierResolver({
8-
resolve: () => Promise.resolve('testAppName'),
6+
void describe('resolveDeployedBackendIdentifier', () => {
7+
void it('returns an App Name and Branch identifier', async () => {
8+
const backendIdResolver = new AppBackendIdentifierResolver({
9+
resolve: () => Promise.resolve('testAppName'),
10+
});
11+
assert.deepStrictEqual(
12+
await backendIdResolver.resolveDeployedBackendIdentifier({
13+
branch: 'test',
14+
}),
15+
{
16+
appName: 'testAppName',
17+
branchName: 'test',
18+
}
19+
);
920
});
10-
assert.deepStrictEqual(
11-
await backendIdResolver.resolve({ branch: 'test' }),
12-
{
13-
appName: 'testAppName',
14-
branchName: 'test',
15-
}
16-
);
17-
});
18-
void it('returns a App Id identifier', async () => {
19-
const backendIdResolver = new AppBackendIdentifierResolver({
20-
resolve: () => Promise.resolve('testAppName'),
21-
});
22-
const actual = await backendIdResolver.resolve({
23-
appId: 'my-id',
24-
branch: 'my-branch',
21+
void it('returns a App Id identifier', async () => {
22+
const backendIdResolver = new AppBackendIdentifierResolver({
23+
resolve: () => Promise.resolve('testAppName'),
24+
});
25+
const actual = await backendIdResolver.resolveDeployedBackendIdentifier({
26+
appId: 'my-id',
27+
branch: 'my-branch',
28+
});
29+
assert.deepStrictEqual(actual, {
30+
namespace: 'my-id',
31+
name: 'my-branch',
32+
type: 'branch',
33+
});
2534
});
26-
assert.deepStrictEqual(actual, {
27-
namespace: 'my-id',
28-
name: 'my-branch',
29-
type: 'branch',
35+
void it('returns a Stack name identifier', async () => {
36+
const backendIdResolver = new AppBackendIdentifierResolver({
37+
resolve: () => Promise.resolve('testAppName'),
38+
});
39+
assert.deepEqual(
40+
await backendIdResolver.resolveDeployedBackendIdentifier({
41+
stack: 'my-stack',
42+
}),
43+
{
44+
stackName: 'my-stack',
45+
}
46+
);
3047
});
3148
});
32-
void it('returns a Stack name identifier', async () => {
33-
const backendIdResolver = new AppBackendIdentifierResolver({
34-
resolve: () => Promise.resolve('testAppName'),
49+
50+
void describe('resolveDeployedBackendIdToBackendId', () => {
51+
void it('returns backend identifier from App Name and Branch identifier', async () => {
52+
const backendIdResolver = new AppBackendIdentifierResolver({
53+
resolve: () => Promise.resolve('testAppName'),
54+
});
55+
assert.deepEqual(
56+
await backendIdResolver.resolveBackendIdentifier({
57+
appId: 'testAppName',
58+
branch: 'test',
59+
}),
60+
{
61+
namespace: 'testAppName',
62+
name: 'test',
63+
type: 'branch',
64+
}
65+
);
3566
});
36-
assert.deepEqual(await backendIdResolver.resolve({ stack: 'my-stack' }), {
37-
stackName: 'my-stack',
67+
void it('returns backend identifier from Stack identifier', async () => {
68+
const backendIdResolver = new AppBackendIdentifierResolver({
69+
resolve: () => Promise.resolve('testAppName'),
70+
});
71+
assert.deepEqual(
72+
await backendIdResolver.resolveBackendIdentifier({
73+
stack: 'amplify-reasonableName-userName-branch-testHash',
74+
}),
75+
{
76+
namespace: 'reasonableName',
77+
name: 'userName',
78+
type: 'branch',
79+
hash: 'testHash',
80+
}
81+
);
3882
});
3983
});
4084
});

packages/cli/src/backend-identifier/backend_identifier_resolver.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { DeployedBackendIdentifier } from '@aws-amplify/deployed-backend-client';
22
import { NamespaceResolver } from './local_namespace_resolver.js';
3+
import { BackendIdentifier } from '@aws-amplify/plugin-types';
4+
import { BackendIdentifierConversions } from '@aws-amplify/platform-core';
35

46
export type BackendIdentifierParameters = {
57
stack?: string;
@@ -8,9 +10,12 @@ export type BackendIdentifierParameters = {
810
};
911

1012
export type BackendIdentifierResolver = {
11-
resolve: (
13+
resolveDeployedBackendIdentifier: (
1214
args: BackendIdentifierParameters
1315
) => Promise<DeployedBackendIdentifier | undefined>;
16+
resolveBackendIdentifier: (
17+
args: BackendIdentifierParameters
18+
) => Promise<BackendIdentifier | undefined>;
1419
};
1520

1621
/**
@@ -22,7 +27,7 @@ export class AppBackendIdentifierResolver implements BackendIdentifierResolver {
2227
* Instantiates BackendIdentifierResolver
2328
*/
2429
constructor(private readonly namespaceResolver: NamespaceResolver) {}
25-
resolve = async (
30+
resolveDeployedBackendIdentifier = async (
2631
args: BackendIdentifierParameters
2732
): Promise<DeployedBackendIdentifier | undefined> => {
2833
if (args.stack) {
@@ -41,4 +46,25 @@ export class AppBackendIdentifierResolver implements BackendIdentifierResolver {
4146
}
4247
return undefined;
4348
};
49+
resolveBackendIdentifier = async (
50+
args: BackendIdentifierParameters
51+
): Promise<BackendIdentifier | undefined> => {
52+
if (args.stack) {
53+
return BackendIdentifierConversions.fromStackName(args.stack);
54+
} else if (args.appId && args.branch) {
55+
return {
56+
namespace: args.appId,
57+
name: args.branch,
58+
type: 'branch',
59+
};
60+
} else if (args.branch) {
61+
return {
62+
namespace: await this.namespaceResolver.resolve(),
63+
name: args.branch,
64+
type: 'branch',
65+
};
66+
}
67+
68+
return undefined;
69+
};
4470
}

packages/cli/src/backend-identifier/backend_identifier_with_sandbox_fallback.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ void it('if backend identifier resolves without error, the resolved id is return
1515
defaultResolver,
1616
sandboxResolver
1717
);
18-
const resolvedId = await backendIdResolver.resolve({
18+
const resolvedId = await backendIdResolver.resolveDeployedBackendIdentifier({
1919
appId: 'hello',
2020
branch: 'world',
2121
});
@@ -45,7 +45,9 @@ void it('uses the sandbox id if the default identifier resolver fails', async ()
4545
defaultResolver,
4646
sandboxResolver
4747
);
48-
const resolvedId = await backendIdResolver.resolve({});
48+
const resolvedId = await backendIdResolver.resolveDeployedBackendIdentifier(
49+
{}
50+
);
4951
assert.deepEqual(resolvedId, {
5052
namespace: appName,
5153
type: 'sandbox',

packages/cli/src/backend-identifier/backend_identifier_with_sandbox_fallback.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,20 @@ export class BackendIdentifierResolverWithFallback
2020
/**
2121
* resolves the backend id, falling back to the sandbox id if there is an error
2222
*/
23-
resolve = async (args: BackendIdentifierParameters) => {
23+
resolveDeployedBackendIdentifier = async (
24+
args: BackendIdentifierParameters
25+
) => {
2426
return (
25-
(await this.defaultResolver.resolve(args)) ??
27+
(await this.defaultResolver.resolveDeployedBackendIdentifier(args)) ??
28+
(await this.fallbackResolver.resolve())
29+
);
30+
};
31+
/**
32+
* Resolves deployed backend id to backend id, falling back to the sandbox id if there is an error
33+
*/
34+
resolveBackendIdentifier = async (args: BackendIdentifierParameters) => {
35+
return (
36+
(await this.defaultResolver.resolveBackendIdentifier(args)) ??
2637
(await this.fallbackResolver.resolve())
2738
);
2839
};

packages/cli/src/commands/generate/forms/generate_forms_command.test.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,14 @@ void describe('generate forms command', () => {
242242
void it('throws user error if the stack deployment is currently in progress', async () => {
243243
const fakeSandboxId = 'my-fake-app-my-fake-username';
244244
const backendIdResolver = {
245-
resolve: mock.fn(() =>
245+
resolveDeployedBackendIdentifier: mock.fn(() =>
246+
Promise.resolve({
247+
namespace: fakeSandboxId,
248+
name: fakeSandboxId,
249+
type: 'sandbox',
250+
})
251+
),
252+
resolveBackendIdentifier: mock.fn(() =>
246253
Promise.resolve({
247254
namespace: fakeSandboxId,
248255
name: fakeSandboxId,
@@ -289,7 +296,14 @@ void describe('generate forms command', () => {
289296
void it('throws user error if the stack does not exist', async () => {
290297
const fakeSandboxId = 'my-fake-app-my-fake-username';
291298
const backendIdResolver = {
292-
resolve: mock.fn(() =>
299+
resolveDeployedBackendIdentifier: mock.fn(() =>
300+
Promise.resolve({
301+
namespace: fakeSandboxId,
302+
name: fakeSandboxId,
303+
type: 'sandbox',
304+
})
305+
),
306+
resolveBackendIdentifier: mock.fn(() =>
293307
Promise.resolve({
294308
namespace: fakeSandboxId,
295309
name: fakeSandboxId,
@@ -333,7 +347,14 @@ void describe('generate forms command', () => {
333347
void it('throws user error if credentials are expired when getting backend outputs', async () => {
334348
const fakeSandboxId = 'my-fake-app-my-fake-username';
335349
const backendIdResolver = {
336-
resolve: mock.fn(() =>
350+
resolveDeployedBackendIdentifier: mock.fn(() =>
351+
Promise.resolve({
352+
namespace: fakeSandboxId,
353+
name: fakeSandboxId,
354+
type: 'sandbox',
355+
})
356+
),
357+
resolveBackendIdentifier: mock.fn(() =>
337358
Promise.resolve({
338359
namespace: fakeSandboxId,
339360
name: fakeSandboxId,
@@ -380,7 +401,14 @@ void describe('generate forms command', () => {
380401
void it('throws user error if access is denied when getting backend outputs', async () => {
381402
const fakeSandboxId = 'my-fake-app-my-fake-username';
382403
const backendIdResolver = {
383-
resolve: mock.fn(() =>
404+
resolveDeployedBackendIdentifier: mock.fn(() =>
405+
Promise.resolve({
406+
namespace: fakeSandboxId,
407+
name: fakeSandboxId,
408+
type: 'sandbox',
409+
})
410+
),
411+
resolveBackendIdentifier: mock.fn(() =>
384412
Promise.resolve({
385413
namespace: fakeSandboxId,
386414
name: fakeSandboxId,

packages/cli/src/commands/generate/forms/generate_forms_command.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ export class GenerateFormsCommand
5252
}
5353

5454
getBackendIdentifier = async (args: GenerateFormsCommandOptions) => {
55-
return await this.backendIdentifierResolver.resolve(args);
55+
return await this.backendIdentifierResolver.resolveDeployedBackendIdentifier(
56+
args
57+
);
5658
};
5759

5860
/**
@@ -61,9 +63,10 @@ export class GenerateFormsCommand
6163
handler = async (
6264
args: ArgumentsCamelCase<GenerateFormsCommandOptions>
6365
): Promise<void> => {
64-
const backendIdentifier = await this.backendIdentifierResolver.resolve(
65-
args
66-
);
66+
const backendIdentifier =
67+
await this.backendIdentifierResolver.resolveDeployedBackendIdentifier(
68+
args
69+
);
6770

6871
if (!backendIdentifier) {
6972
throw new Error('Could not resolve the backend identifier');

packages/cli/src/commands/generate/graphql-client-code/generate_graphql_client_code_command.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,10 @@ export class GenerateGraphqlClientCodeCommand
8989
handler = async (
9090
args: ArgumentsCamelCase<GenerateGraphqlClientCodeCommandOptions>
9191
): Promise<void> => {
92-
const backendIdentifier = await this.backendIdentifierResolver.resolve(
93-
args
94-
);
92+
const backendIdentifier =
93+
await this.backendIdentifierResolver.resolveDeployedBackendIdentifier(
94+
args
95+
);
9596
const out = this.getOutDir(args);
9697
const format = args.format ?? GenerateApiCodeFormat.GRAPHQL_CODEGEN;
9798
const formatParams = this.formatParamBuilders[format](args);

packages/cli/src/commands/generate/outputs/generate_outputs_command.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@ export class GenerateOutputsCommand
5454
handler = async (
5555
args: ArgumentsCamelCase<GenerateOutputsCommandOptions>
5656
): Promise<void> => {
57-
const backendIdentifier = await this.backendIdentifierResolver.resolve(
58-
args
59-
);
57+
const backendIdentifier =
58+
await this.backendIdentifierResolver.resolveDeployedBackendIdentifier(
59+
args
60+
);
6061

6162
if (!backendIdentifier) {
6263
throw new Error('Could not resolve the backend identifier');

packages/cli/src/commands/generate/schema-from-database/generate_schema_command.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,15 @@ void describe('generate graphql-client-code command', () => {
117117

118118
void it('generates and writes schema for stack', async () => {
119119
await commandRunner.runCommand(
120-
'schema-from-database --stack stack_name --connection-uri-secret CONN_STRING --out schema.rds.ts'
120+
'schema-from-database --stack amplify-reasonableName-userName-sandbox-testHash --connection-uri-secret CONN_STRING --out schema.rds.ts'
121121
);
122122
assert.equal(secretClientGetSecret.mock.callCount(), 1);
123+
assert.deepEqual(secretClientGetSecret.mock.calls[0].arguments[0], {
124+
namespace: 'reasonableName',
125+
name: 'userName',
126+
type: 'sandbox',
127+
hash: 'testHash',
128+
});
123129
assert.equal(schemaGeneratorGenerateMethod.mock.callCount(), 1);
124130
assert.deepEqual(schemaGeneratorGenerateMethod.mock.calls[0].arguments[0], {
125131
connectionUri: {

0 commit comments

Comments
 (0)