infrastructure-components
Version:
Infrastructure-Components configure the infrastructure of your React-App as part of your React-Components.
250 lines (245 loc) • 13.9 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* This module must not import anything globally not workin in web-mode! if needed, require it within the functions
*
* NOTE, we Ignore the infrastructure-scripts libraries when bundling, so these can be used ...
* We also put fs to empty! If you need other libs, add them to `node: { fs: empty }`
*/
const spa_component_1 = require("./spa-component");
const deepmerge = __importStar(require("deepmerge"));
const parser_1 = require("../libs/parser");
const extract_domain_1 = __importDefault(require("extract-domain"));
/**
* A Plugin to detect SinglePage-App-Components
* @param props
*/
exports.SpaPlugin = (props) => {
//console.log("configFilePath: " , props.configFilePath);
const result = {
// identify Isomorphic-App-Components
applies: (component) => {
return spa_component_1.isSinglePageApp(component);
},
// convert the component into configuration parts
process: (component, childConfigs, infrastructureMode) => {
const path = require('path');
const webappBuildPath = path.join(require("../../../infrastructure-scripts/dist/infra-comp-utils/system-libs").currentAbsolutePath(), props.buildPath);
const spaWebPack = require("../../../infrastructure-scripts/dist/infra-comp-utils/webpack-libs")
.complementWebpackConfig(require("../../../infrastructure-scripts/dist/infra-comp-utils/webpack-libs")
.createClientWebpackConfig("./" + path.join("node_modules", "infrastructure-components", "dist", "assets", "spa.js"), //entryPath: string,
path.join(require("../../../infrastructure-scripts/dist/infra-comp-utils/system-libs").currentAbsolutePath(), props.buildPath), //use the buildpath from the parent plugin
component.id, //appName
undefined, //assetsPath
undefined, // stagePath: TODO take from Environment!
{
__CONFIG_FILE_PATH__: require("../../../infrastructure-scripts/dist/infra-comp-utils/system-libs").pathToConfigFile(props.configFilePath),
// required of the routed-app
"react-router-dom": path.join(require("../../../infrastructure-scripts/dist/infra-comp-utils/system-libs").currentAbsolutePath(), "node_modules", "react-router-dom"),
// required of the data-layer / apollo
"react-apollo": path.join(require("../../../infrastructure-scripts/dist/infra-comp-utils/system-libs").currentAbsolutePath(), "node_modules", "react-apollo"),
}, {}), props.parserMode === parser_1.PARSER_MODES.MODE_DEPLOY //isProd
);
// provide all client configs in a flat list
const webpackConfigs = childConfigs.reduce((result, config) => result.concat(config.webpackConfigs), []);
const createHtml = () => {
//console.log("check for >>copyAssetsPostBuild<<");
//if (props.parserMode == PARSER_MODES.MODE_BUILD) {
console.log("write the index.html!");
require('fs').writeFileSync(path.join(webappBuildPath, component.stackName, "index.html"), `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>${component.stackName}</title>
<style>
body {
display: block;
margin: 0px;
}
</style>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="${component.stackName}.bundle.js"></script>
</body>
</html>`);
};
// check whether we already created the domain of this environment
const deployedDomain = process.env[`DOMAIN_${props.stage}`] !== undefined;
const domain = childConfigs.map(config => config.domain).reduce((result, domain) => result !== undefined ? result : domain, undefined);
const certArn = childConfigs.map(config => config.certArn).reduce((result, certArn) => result !== undefined ? result : certArn, undefined);
const invalidateCloudFrontCache = () => {
if (deployedDomain && props.parserMode === parser_1.PARSER_MODES.MODE_DEPLOY) {
require("../../../infrastructure-scripts/dist/infra-comp-utils/sls-libs").invalidateCloudFrontCache(domain);
}
};
const hostedZoneName = domain !== undefined ? extract_domain_1.default(domain.toString()) : {};
/** post build function to write to the .env file that the domain has been deployed */
const writeDomainEnv = () => {
//console.log("check for >>writeDomainEnv<<");
// we only write to the .env file when we are in domain mode, i.e. this script creates the domain
// and we did not yet deployed the domain previously
if (!deployedDomain && props.parserMode === parser_1.PARSER_MODES.MODE_DOMAIN) {
require('fs').appendFileSync(path.join(require("../../../infrastructure-scripts/dist/infra-comp-utils/system-libs").currentAbsolutePath(), ".env"), `\nDOMAIN_${props.stage}=TRUE`);
}
};
/*
const postDeploy = async () => {
//console.log("check for >>showStaticPageName<<");
if (props.parserMode === PARSER_MODES.MODE_DEPLOY) {
await require('../libs/scripts-libs').fetchData("deploy", {
proj: component.stackName,
envi: props.stage,
domain: domain,
endp: `http://${component.stackName}-${props.stage}.s3-website-${component.region}.amazonaws.com`
});
console.log(`Your SinglePageApp is now available at: http://${component.stackName}-${props.stage}.s3-website-${component.region}.amazonaws.com`);
}
};*/
function deployWithDomain() {
return __awaiter(this, void 0, void 0, function* () {
// start the sls-config
if (props.parserMode === parser_1.PARSER_MODES.MODE_DOMAIN) {
yield require("../../../infrastructure-scripts/dist/infra-comp-utils/sls-libs").deploySls(component.stackName);
}
});
}
/**
* ONLY add the domain config if we are in domain mode!
* TODO once the domain has been added, we need to add this with every deployment
*/
const domainConfig = (props.parserMode === parser_1.PARSER_MODES.MODE_DOMAIN || deployedDomain) &&
domain !== undefined && certArn !== undefined ? {
// required of the SPA-domain-alias
provider: {
customDomainName: domain,
hostedZoneName: hostedZoneName,
certArn: certArn
},
resources: {
Resources: {
WebAppCloudFrontDistribution: {
Type: "AWS::CloudFront::Distribution",
Properties: {
DistributionConfig: {
Origins: [
{
DomainName: "${self:provider.staticBucket}.s3.amazonaws.com",
Id: component.stackName,
CustomOriginConfig: {
HTTPPort: 80,
HTTPSPort: 443,
OriginProtocolPolicy: "https-only",
}
}
],
Enabled: "'true'",
DefaultRootObject: "index.html",
CustomErrorResponses: [{
ErrorCode: 404,
ResponseCode: 200,
ResponsePagePath: "/index.html"
}],
DefaultCacheBehavior: {
AllowedMethods: [
"DELETE",
"GET",
"HEAD",
"OPTIONS",
"PATCH",
"POST",
"PUT"
],
TargetOriginId: component.stackName,
ForwardedValues: {
QueryString: "'false'",
Cookies: {
Forward: "none"
}
},
ViewerProtocolPolicy: "redirect-to-https"
},
ViewerCertificate: {
AcmCertificateArn: "${self:provider.certArn}",
SslSupportMethod: "sni-only",
},
Aliases: ["${self:provider.customDomainName}"]
}
}
},
DnsRecord: {
Type: "AWS::Route53::RecordSet",
Properties: {
AliasTarget: {
DNSName: "!GetAtt WebAppCloudFrontDistribution.DomainName",
HostedZoneId: "Z2FDTNDATAQYW2"
},
HostedZoneName: "${self:provider.hostedZoneName}.",
Name: "${self:provider.customDomainName}.",
Type: "'A'"
}
}
},
Outputs: {
WebAppCloudFrontDistributionOutput: {
Value: {
"Fn::GetAtt": "[ WebAppCloudFrontDistribution, DomainName ]"
}
}
}
}
} : {};
return {
stackType: "SPA",
slsConfigs: deepmerge.all([
require("../../../infrastructure-scripts/dist/infra-comp-utils/sls-libs").toSpaSlsConfig(component.stackName, component.buildPath, component.region, domain),
domainConfig,
{
plugins: ["serverless-pseudo-parameters"],
/** we need to add a dummy value-anything-to custom. Otherwise, the pseudo-parameters plugin doesn't work*/
custom: {
dummy: "none"
}
},
...childConfigs.map(config => config.slsConfigs)
]),
// add the server config
webpackConfigs: webpackConfigs.concat([spaWebPack]),
postBuilds: childConfigs.reduce((result, config) => result.concat(config.postBuilds), [createHtml, writeDomainEnv, deployWithDomain, invalidateCloudFrontCache /*, postDeploy*/]),
iamRoleStatements: [],
environments: childConfigs.reduce((result, config) => (result !== undefined ? result : []).concat(config.environments !== undefined ? config.environments : []), []),
stackName: component.stackName,
assetsPath: undefined,
buildPath: component.buildPath,
region: component.region,
domain: domain,
certArn: certArn,
// start the sls-stack offline does not work and does make sense either, we can use the hot-dev-mode
supportOfflineStart: false,
supportCreateDomain: true
};
}
};
return result;
};
//# sourceMappingURL=spa-plugin.js.map
;