Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,12 @@ describe('BackendRenderer', () => {
expect(output).toContain('enableTokenRevocation: true');
expect(output).toContain('enablePropagateAdditionalUserContextData: true');
expect(output).toContain('generateSecret: true');

expect(output).toContain(
'const providerSetupResult = (backend.auth.stack.node.children.find(child => child.node.id === "amplifyAuth") as any).providerSetupResult;',
);
expect(output).toContain('Object.keys(providerSetupResult).forEach(provider => {');
expect(output).toContain('userPoolClient.node.addDependency(providerSetupPropertyValue)');
});
it('renders userpool and identitypool deletion policy', () => {
const renderer = new BackendSynthesizer();
Expand Down
179 changes: 173 additions & 6 deletions packages/amplify-gen2-codegen/src/backend/synthesizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,25 @@ export class BackendSynthesizer {
userPoolClientAttributesMap.set('ExplicitAuthFlows', 'authFlows');
userPoolClientAttributesMap.set('AllowedOAuthFlows', 'flows');

const nativeUserPoolClientExpressionStatement = factory.createExpressionStatement(
factory.createCallExpression(
factory.createPropertyAccessExpression(factory.createIdentifier('userPool'), factory.createIdentifier('addClient')),
undefined,
[factory.createStringLiteral('NativeAppClient'), this.createNestedObjectExpression(userPoolClient, userPoolClientAttributesMap)],
const userPoolClientDeclaration = factory.createVariableStatement(
undefined,
factory.createVariableDeclarationList(
[
factory.createVariableDeclaration(
factory.createIdentifier('userPoolClient'),
undefined,
undefined,
factory.createCallExpression(
factory.createPropertyAccessExpression(factory.createIdentifier('userPool'), factory.createIdentifier('addClient')),
undefined,
[
factory.createStringLiteral('NativeAppClient'),
this.createNestedObjectExpression(userPoolClient, userPoolClientAttributesMap),
],
),
),
],
ts.NodeFlags.Const,
),
);

Expand All @@ -225,7 +239,157 @@ export class BackendSynthesizer {
}
}

return nativeUserPoolClientExpressionStatement;
return userPoolClientDeclaration;
}

private createPropertyAccessChain(identifiers: string[]): ts.Expression {
return identifiers
.slice(1)
.reduce<ts.Expression>(
(acc, curr) => factory.createPropertyAccessExpression(acc, factory.createIdentifier(curr)),
factory.createIdentifier(identifiers[0]),
);
}

private getProviderSetupDeclaration(): ts.VariableStatement {
const providerSetupResult = 'providerSetupResult';
return factory.createVariableStatement(
undefined,
factory.createVariableDeclarationList(
[
factory.createVariableDeclaration(
factory.createIdentifier(providerSetupResult),
undefined,
undefined,
factory.createPropertyAccessExpression(
factory.createParenthesizedExpression(
factory.createAsExpression(
factory.createCallExpression(
factory.createPropertyAccessExpression(
this.createPropertyAccessChain(['backend', 'auth', 'stack', 'node', 'children']),
factory.createIdentifier('find'),
),
undefined,
[
factory.createArrowFunction(
undefined,
undefined,
[factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier('child'))],
undefined,
factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
factory.createBinaryExpression(
this.createPropertyAccessChain(['child', 'node', 'id']),
factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken),
factory.createStringLiteral('amplifyAuth'),
),
),
],
),
factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword),
),
),
factory.createIdentifier(providerSetupResult),
),
),
],
ts.NodeFlags.Const,
),
);
}

private getProviderSetupForeachStatement(): ExpressionStatement {
const providerSetupResult = 'providerSetupResult';
return factory.createExpressionStatement(
factory.createCallExpression(
factory.createPropertyAccessExpression(
factory.createCallExpression(
factory.createPropertyAccessExpression(factory.createIdentifier('Object'), factory.createIdentifier('keys')),
undefined,
[factory.createIdentifier(providerSetupResult)],
),
factory.createIdentifier('forEach'),
),
undefined,
[
factory.createArrowFunction(
undefined,
undefined,
[factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier('provider'))],
undefined,
factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
factory.createBlock(
[
// const providerSetupPropertyValue = providerSetupResult[provider]
factory.createVariableStatement(
undefined,
factory.createVariableDeclarationList(
[
factory.createVariableDeclaration(
factory.createIdentifier('providerSetupPropertyValue'),
undefined,
undefined,
factory.createElementAccessExpression(
factory.createIdentifier(providerSetupResult),
factory.createIdentifier('provider'),
),
),
],
ts.NodeFlags.Const,
),
),
// if condition
factory.createIfStatement(
factory.createLogicalAnd(
factory.createPropertyAccessExpression(
factory.createIdentifier('providerSetupPropertyValue'),
factory.createIdentifier('node'),
),
factory.createCallExpression(
factory.createPropertyAccessExpression(
factory.createCallExpression(
factory.createPropertyAccessExpression(
this.createPropertyAccessChain(['providerSetupPropertyValue', 'node', 'id']),
factory.createIdentifier('toLowerCase'),
),
undefined,
[],
),
factory.createIdentifier('endsWith'),
),
undefined,
[factory.createStringLiteral('idp')],
),
),
factory.createBlock(
[
factory.createExpressionStatement(
factory.createCallExpression(
this.createPropertyAccessChain(['userPoolClient', 'node', 'addDependency']),
undefined,
[factory.createIdentifier('providerSetupPropertyValue')],
),
),
],
true,
),
),
],
true,
),
),
],
),
);
}

private createProviderSetupCode(): ts.Statement[] {
// Create const providerSetupResult = (backend.auth.stack.node.children.find(child => child.node.id === "amplifyAuth") as any).providerSetupResult;
const providerSetupDeclaration = this.getProviderSetupDeclaration();

// Create Object.keys(providerSetupResult).forEach(...)
const forEachStatement = this.getProviderSetupForeachStatement();

return [providerSetupDeclaration, forEachStatement];
}

private createNestedObjectExpression(object: Record<string, any>, gen2PropertyMap: Map<string, string>): ts.ObjectLiteralExpression {
Expand Down Expand Up @@ -743,6 +907,9 @@ export class BackendSynthesizer {
const userPoolVariableStatement = this.createVariableStatement(this.createVariableDeclaration('userPool', 'auth.resources.userPool'));
nodes.push(userPoolVariableStatement);
nodes.push(this.createUserPoolClientAssignment(renderArgs.auth?.userPoolClient, imports));

const idpStatements = this.createProviderSetupCode();
nodes.push(...idpStatements);
}

if (renderArgs.storage && renderArgs.storage.hasS3Bucket) {
Expand Down
1 change: 1 addition & 0 deletions packages/amplify-gen2-codegen/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export const createGen2Renderer = ({
module: 'es2022',
moduleResolution: 'bundler',
resolveJsonModule: true,
// eslint-disable-next-line spellcheck/spell-checker
esModuleInterop: true,
forceConsistentCasingInFileNames: true,
strict: true,
Expand Down
29 changes: 20 additions & 9 deletions packages/amplify-migration/src/app_auth_definition_fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class AppAuthDefinitionFetcher {
return JSON.parse(contents);
};

private getReferenceAuth = async () => {
private getAuthCategory = async () => {
const backendEnvironment = await this.backendEnvironmentResolver.selectBackendEnvironment();
if (!backendEnvironment?.deploymentArtifacts) return undefined;
const currentCloudBackendDirectory = await this.ccbFetcher.getCurrentCloudBackend(backendEnvironment.deploymentArtifacts);
Expand All @@ -51,12 +51,19 @@ export class AppAuthDefinitionFetcher {
}

const amplifyMeta = (await this.readJsonFile(amplifyMetaPath)) ?? {};
const isImported =
'auth' in amplifyMeta &&
Object.keys(amplifyMeta.auth).length > 0 &&
Object.entries(amplifyMeta.auth).some(
([, value]) => typeof value === 'object' && value !== null && 'serviceType' in value && value.serviceType === 'imported',
);
const authCategory = 'auth' in amplifyMeta && Object.keys(amplifyMeta.auth).length > 0;

if (authCategory) {
return amplifyMeta.auth;
} else {
return undefined;
}
};

private getReferenceAuth = async (authCategory: any) => {
const isImported = Object.entries(authCategory).some(
([, value]) => typeof value === 'object' && value !== null && 'serviceType' in value && value.serviceType === 'imported',
);
if (!isImported) {
return undefined;
}
Expand All @@ -65,7 +72,7 @@ export class AppAuthDefinitionFetcher {
UserPoolId: userPoolId,
AppClientIDWeb: userPoolClientId,
IdentityPoolId: identityPoolId,
} = Object.keys(amplifyMeta.auth).map((key) => amplifyMeta.auth[key])[0].output;
} = Object.keys(authCategory).map((key) => authCategory[key])[0].output;
if (!userPoolId && !userPoolClientId && !identityPoolId) {
throw new Error('No user pool or identity pool found for import.');
}
Expand Down Expand Up @@ -116,7 +123,11 @@ export class AppAuthDefinitionFetcher {
};

getDefinition = async (): Promise<AuthDefinition | undefined> => {
const referenceAuth = await this.getReferenceAuth();
const authCategory = await this.getAuthCategory();
if (!authCategory) {
return undefined;
}
const referenceAuth = await this.getReferenceAuth(authCategory);
if (referenceAuth) {
return {
referenceAuth,
Expand Down
4 changes: 2 additions & 2 deletions packages/amplify-migration/src/command-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ frontend:
});
});

it('should throw an error if buildSpec is not found in the app', async () => {
it('should not throw an error if buildSpec is not found in the app', async () => {
(fs.readFile as jest.Mock).mockRejectedValue({ code: 'ENOENT' });
(AmplifyClient.prototype.send as jest.Mock).mockResolvedValue({
app: {},
});

await expect(updateAmplifyYmlFile(amplifyClient, mockAppId)).rejects.toThrow('buildSpec not found in the app');
await expect(updateAmplifyYmlFile(amplifyClient, mockAppId)).resolves.not.toThrow();
});

it('should throw an error if app is not found', async () => {
Expand Down
6 changes: 4 additions & 2 deletions packages/amplify-migration/src/command-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,10 @@ export async function updateAmplifyYmlFile(amplifyClient: AmplifyClient, appId:

assert(getAppResponse.app, 'App not found');
const buildSpec = getAppResponse.app.buildSpec;
assert(buildSpec, 'buildSpec not found in the app');

await writeToAmplifyYmlFile(amplifyYmlPath, buildSpec);
if (buildSpec) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

await writeToAmplifyYmlFile(amplifyYmlPath, buildSpec);
}
} else {
// Throw the original error if it's not related to file not found
throw error;
Expand All @@ -241,6 +242,7 @@ export async function updateAmplifyYmlFile(amplifyClient: AmplifyClient, appId:
}

async function writeToAmplifyYmlFile(amplifyYmlPath: string, content: string) {
// eslint-disable-next-line spellcheck/spell-checker
// Replace 'amplifyPush --simple' with 'npx ampx pipeline-deploy'
content = content.replace(new RegExp(GEN1_COMMAND, 'g'), GEN2_COMMAND);
await fs.writeFile(amplifyYmlPath, content, { encoding: 'utf-8' });
Expand Down
Loading