Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into category-auth/sig…
Browse files Browse the repository at this point in the history
…n-in-with-apple
  • Loading branch information
David Lopez committed May 6, 2021
2 parents c6fae5e + 338cea2 commit 076ef29
Show file tree
Hide file tree
Showing 18 changed files with 430 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The AWS Amplify CLI is a toolchain which includes a robust feature set for simpl

## Install the CLI

- Requires Node.js® version 10 or later
- Requires Node.js® version 12 or later

Install and configure the Amplify CLI as follows:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Resources:
Mutable: true
<% } %>
<% } %>
<%if (!props.breakCircularDependency && props.triggers !== '{}' && props.dependsOn) { %>
<%if (!props.breakCircularDependency && props.triggers && props.dependsOn) { %>
LambdaConfig:
<%if (props.dependsOn.find(i => i.resourceName.includes('CreateAuthChallenge'))) { %>
CreateAuthChallenge: !Ref function<%=props.resourceName%>CreateAuthChallengeArn
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { getSuitableFrontend } from '../../init-steps/s1-initFrontend';

describe('getSuitableFrontend', () => {
it('supports headless inputs', () => {
const context = {
exeInfo: {
inputParams: {
amplify: {
frontend: 'ios',
},
},
},
} as any;
const frontendPlugins = { ios: '' } as any;
const result = getSuitableFrontend(context, frontendPlugins, '');
expect(result).toStrictEqual('ios');
});
});
2 changes: 1 addition & 1 deletion packages/amplify-cli/src/init-steps/s0-analyzeProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ async function displayAndSetDefaults(context: $TSContext, projectPath: string, p
await displayConfigurationDefaults(context, defaultProjectName, defaultEnv, defaultEditorName);

const frontendPlugins = getFrontendPlugins(context);
const defaultFrontend = getSuitableFrontend(frontendPlugins, projectPath);
const defaultFrontend = getSuitableFrontend(context, frontendPlugins, projectPath);
const frontendModule = require(frontendPlugins[defaultFrontend]);

await frontendModule.displayFrontendDefaults(context, projectPath);
Expand Down
10 changes: 8 additions & 2 deletions packages/amplify-cli/src/init-steps/s1-initFrontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export async function initFrontend(context: $TSContext) {
}

const frontendPlugins = getFrontendPlugins(context);
const suitableFrontend = getSuitableFrontend(frontendPlugins, context.exeInfo.localEnvInfo.projectPath);
const suitableFrontend = getSuitableFrontend(context, frontendPlugins, context.exeInfo.localEnvInfo.projectPath);
const frontend = await getFrontendHandler(context, frontendPlugins, suitableFrontend);

context.exeInfo.projectConfig.frontend = frontend;
Expand All @@ -22,7 +22,13 @@ export async function initFrontend(context: $TSContext) {
return context;
}

export function getSuitableFrontend(frontendPlugins: $TSAny, projectPath: string) {
export function getSuitableFrontend(context: $TSContext, frontendPlugins: $TSAny, projectPath: string) {
let headlessFrontend = context?.exeInfo?.inputParams?.amplify?.frontend;

if (headlessFrontend && headlessFrontend in frontendPlugins) {
return headlessFrontend;
}

let suitableFrontend;
let fitToHandleScore = -1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const resolvePackageRoot = (packageName: string) => {
// Registry of packages that have files that need to be copied to the .amplify folder on CLI installation
const copyPkgAssetRegistry = [
'amplify-dynamodb-simulator',
'amplify-frontend-ios',
'amplify-go-function-runtime-provider',
'amplify-java-function-runtime-provider',
'amplify-python-function-runtime-provider',
Expand Down
36 changes: 25 additions & 11 deletions packages/amplify-frontend-ios/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const path = require('path');
const amplifyApp = require('amplify-app');
const { FeatureFlags } = require('amplify-cli-core');
const { FeatureFlags, pathManager } = require('amplify-cli-core');
const { importConfig, importModels } = require('./lib/amplify-xcode');
const initializer = require('./lib/initializer');
const projectScanner = require('./lib/project-scanner');
const configManager = require('./lib/configuration-manager');
Expand Down Expand Up @@ -59,22 +59,35 @@ async function executeAmplifyCommand(context) {
await commandModule.run(context);
}

const postEvents = new Set(['PostInit', 'PostCodegenModels', 'PostPull']);

async function handleAmplifyEvent(context, args) {
const { frontend } = context.amplify.getProjectConfig();
const isXcodeIntegrationEnabled = FeatureFlags.getBoolean('frontend-ios.enableXcodeIntegration');
const isFrontendiOS = frontend === 'ios';
if (isFrontendiOS && isXcodeIntegrationEnabled && postEvents.has(args.event)) {
await amplifyApp.run({
skipEnvCheck: true,
platform: frontend,
skipInit: true,
internalOnlyIosCallback: true,
});
const isMacOs = process.platform === 'darwin';
if (!isFrontendiOS || !isXcodeIntegrationEnabled || !isMacOs) {
return;
}
context.print.info('Updating iOS project');
const projectPath = pathManager.findProjectRoot();
switch (args.event) {
case 'PostInit':
await importConfig({ path: projectPath });
break;
case 'PostCodegenModels':
await importModels({ path: projectPath });
break;
case 'PostPull':
await importConfig({ path: projectPath });
await importModels({ path: projectPath });
break;
default:
break;
}
context.print.info('Amplify setup completed successfully.');
}

const getPackageAssetPaths = async () => ['resources'];

module.exports = {
constants,
scanProject,
Expand All @@ -89,4 +102,5 @@ module.exports = {
executeAmplifyCommand,
handleAmplifyEvent,
deleteConfig: deleteAmplifyConfig,
getPackageAssetPaths,
};
71 changes: 71 additions & 0 deletions packages/amplify-frontend-ios/lib/amplify-xcode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// A copy of the License is located at
//
// http://aws.amazon.com/apache2.0
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
//

// ############################################################################
// Auto-generated file using `build` NPM script. Do not edit this file manually
// ############################################################################

const execa = require('execa');
const path = require('path');
const { pathManager } = require('amplify-cli-core');

const BINARY_PATH = 'resources/amplify-xcode';
const PACKAGE_NAME = 'amplify-frontend-ios';
const amplifyXcodePath = () => path.join(pathManager.getAmplifyPackageLibDirPath(PACKAGE_NAME), BINARY_PATH);

/**
* Import Amplify configuration files
* @param {Object} params
* @param {String} params.path - Project base path
*/
async function importConfig(params) {
let command = `${amplifyXcodePath()} import-config`;
if (params['path']) {
command += ` --path=${params['path']}`;
}
await execa.command(command, { stdout: 'inherit' });
}

/**
* Import Amplify models
* @param {Object} params
* @param {String} params.path - Project base path
*/
async function importModels(params) {
let command = `${amplifyXcodePath()} import-models`;
if (params['path']) {
command += ` --path=${params['path']}`;
}
await execa.command(command, { stdout: 'inherit' });
}

/**
* Generates a JSON description of the CLI and its commands
* @param {Object} params
* @param {String} params.output-path - Path to save the output of generated schema file
*/
async function generateSchema(params) {
let command = `${amplifyXcodePath()} generate-schema`;
if (params['output-path']) {
command += ` --output-path=${params['output-path']}`;
}
await execa.command(command, { stdout: 'inherit' });
}

module.exports = {
importConfig,
importModels,
generateSchema,
};
127 changes: 127 additions & 0 deletions packages/amplify-frontend-ios/native-bindings-codegen/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
const path = require('path');
const fs = require('fs');
const _ = require('lodash');

const CODEGEN_TEMPLATES_FOLDER = 'templates';

const canonicalFunctionName = commandName => _.camelCase(commandName);

const getTemplate = templatName => {
const templatePath = path.join(__dirname, CODEGEN_TEMPLATES_FOLDER, templatName);
const template = fs.readFileSync(templatePath).toString();
return _.template(template, { interpolate: /<%=([\s\S]+?)%>/g });
};

/**
* Generates function signature docs
* @param {String} abstract
* @param {Array<{name: String, type: String, help: String}>} parameters
*/
const generateFunctionDocs = (abstract, parameters) => {
return `
/**
* ${abstract}
* @param {Object} params
${parameters.map(p => ` * @param {${p.type}} params.${p.name} - ${p.help}`).join('\n')}
*/`;
};

/**
* Given a list of parameters of type `Parameter` generates
* proper CLI call signature.
* Parameter {
* kind: option | flag | argument
* name: string
* type: string
* help: string
* }
* @param {Array<{
* name: String,
* kind:"option" | "flag" | "argument"
* type: String,
* help: String}>} parameters
* @returns {Array<Array<String>>}
*/
const generateCommandParameters = parameters => {
return parameters.map(param => {
const { kind, name } = param;
const funcParamValue = `params['${name}']`;
let output;
switch (kind) {
case 'option':
output = [`if (${funcParamValue}) {`, ` command += \` --${name}=\${${funcParamValue}}\`;`, ` }`];
break;
case 'flag':
output = [`if (${funcParamValue}) {`, ` command += \` --${name}\`;`, ` }`];
break;
case 'argument':
output = [` command += \` \${${funcParamValue}}\`;`];
}
return output;
});
};

/**
* Given a command schema generates data used in
* template function declaration
* @param {Object} commandSchema
* @param {String} commandSchema.abstract
* @param {String} commandSchema.name
* @param {Array} commandSchema.parameters
*/
const generateFunctionBodyData = commandSchema => {
const { abstract, name, parameters } = commandSchema;
return {
__FUNCTION_DOCS__: generateFunctionDocs(abstract, parameters),
__FUNCTION_NAME__: canonicalFunctionName(name),
__COMMAND_NAME__: name,
__COMMAND_PARAMS__: generateCommandParameters(parameters)
.map(p => ` ${p.join('\n')}`)
.join('\n'),
};
};

/**
* Given an `amplify-xcode` schema, generates the commonjs
* exported module declaration
* @param {Object} schema amplify-xcode schema @see amplify-xcode.json
*/
const generateModuleExports = schema => {
let output = ['module.exports = {'];
schema.commands.forEach(command => {
output.push(` ${canonicalFunctionName(command.name)},`);
});
output.push('};');

return output;
};

/**
* Given an `amplify-xcode` schema, generates JS
* bindings to safely call `amplify-xcode`.
* @param {Object} schema amplify-xcode schema
* @param {String} outputPath generated JS bindings file path
*/
const generateNativeBindings = (schema, outputPath) => {
const preamble = getTemplate('preamble.jst')();
const functionTemplate = getTemplate('function.jst');
// generate functions body
let output = preamble;
output += schema.commands
.map(command => {
return functionTemplate(generateFunctionBodyData(command));
})
.join('');

// generate exports
output += '\n' + generateModuleExports(schema).join('\n') + '\n';

fs.writeFileSync(outputPath, output);
};

module.exports = {
generateCommandParameters,
generateFunctionBodyData,
generateModuleExports,
generateNativeBindings,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<%= __FUNCTION_DOCS__ %>
async function <%= __FUNCTION_NAME__ %>(params) {
let command = `${amplifyXcodePath()} <%= __COMMAND_NAME__ %>`;
<%=__COMMAND_PARAMS__ %>
await execa.command(command, { stdout: 'inherit' });
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// A copy of the License is located at
//
// http://aws.amazon.com/apache2.0
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
//

// ############################################################################
// Auto-generated file using `build` NPM script. Do not edit this file manually
// ############################################################################

const execa = require('execa');
const path = require('path');
const { pathManager } = require('amplify-cli-core');

const BINARY_PATH = 'resources/amplify-xcode';
const PACKAGE_NAME = 'amplify-frontend-ios';
const amplifyXcodePath = () => path.join(pathManager.getAmplifyPackageLibDirPath(PACKAGE_NAME), BINARY_PATH);
7 changes: 5 additions & 2 deletions packages/amplify-frontend-ios/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@
"aws"
],
"scripts": {
"generate-xcode-bindings": "node ./scripts/native-bindings-gen",
"test": "jest",
"test-watch": "jest --watch"
},
"dependencies": {
"amplify-app": "2.23.5",
"amplify-cli-core": "1.21.2",
"execa": "^4.1.0",
"fs-extra": "^8.1.0",
"graphql-config": "^2.2.1"
"graphql-config": "^2.2.1",
"lodash": "^4.17.21"
},
"jest": {
"collectCoverage": true,
Expand Down
Binary file not shown.
Loading

0 comments on commit 076ef29

Please sign in to comment.