Skip to content

Commit

Permalink
feat: improve Webiny / create-webiny-project CLIs (#4045)
Browse files Browse the repository at this point in the history
  • Loading branch information
adrians5j authored Mar 19, 2024
1 parent c9d8163 commit 16b0da1
Show file tree
Hide file tree
Showing 130 changed files with 3,080 additions and 1,915 deletions.
4 changes: 4 additions & 0 deletions packages/api-wcp/src/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export const createWcpGraphQL = () => {
}
type WcpProject {
orgId: ID
projectId: ID
package: WcpProjectPackage
}
Expand Down Expand Up @@ -75,6 +77,8 @@ export const createWcpGraphQL = () => {
}

return new Response({
orgId: projectLicense.orgId,
projectId: projectLicense.projectId,
package: projectLicense.package
});
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, { useMemo } from "react";
import styled from "@emotion/styled";
import { useWcp } from "@webiny/app-admin";
import { ListItem } from "@webiny/ui/List";
import { subFooter } from "./Styled";
import { config as appConfig } from "@webiny/app/config";
import { Typography } from "@webiny/ui/Typography";
import { Tooltip } from "@webiny/ui/Tooltip";

const WcpBadge = styled.div`
background-color: var(--mdc-theme-primary, #6200ee);
display: inline-block;
color: white;
padding: 2px 4px;
border-radius: 5px;
font-size: 12px;
font-weight: bold;
line-height: 14px;
margin-left: 5px;
`;

export const WebinyVersionListItem = () => {
const wbyVersion = appConfig.getKey("WEBINY_VERSION", process.env.REACT_APP_WEBINY_VERSION);
const wcp = useWcp();

const wcpBadge = useMemo(() => {
const wcpProject = wcp.getProject();
if (!wcpProject) {
return null;
}

const tooltipContent = (
<span>
{wcpProject.orgId}/{wcpProject.projectId}
</span>
);

return (
<Tooltip content={tooltipContent}>
<WcpBadge>WCP</WcpBadge>
</Tooltip>
);
}, []);

return (
<ListItem ripple={false} className={subFooter}>
<Typography use={"body2"}>
Webiny v{wbyVersion}
{wcpBadge}
</Typography>
</ListItem>
);
};
27 changes: 11 additions & 16 deletions packages/app-admin-rmwc/src/modules/Navigation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,26 @@ import React, { Fragment, useCallback, useContext, useMemo, useState } from "rea
import styled from "@emotion/styled";
import { Drawer, DrawerContent, DrawerHeader } from "@webiny/ui/Drawer";
import {
Compose,
Provider,
NavigationRenderer as NavigationSpec,
MenuItems,
MenuItemRenderer,
Brand as BrandSpec,
useNavigation as useAdminNavigation,
Compose,
HigherOrderComponent,
MenuData,
MenuItemRenderer,
MenuItems,
MenuItemsProps,
HigherOrderComponent
NavigationRenderer as NavigationSpec,
Provider,
useNavigation as useAdminNavigation
} from "@webiny/app-admin";
import Hamburger from "./Hamburger";
import { MenuGroupRenderer } from "./renderers/MenuGroupRenderer";
import { MenuSectionItemRenderer } from "./renderers/MenuSectionItemRenderer";
import { MenuSectionRenderer } from "./renderers/MenuSectionRenderer";
import { MenuLinkRenderer } from "./renderers/MenuLinkRenderer";
import { MenuElementRenderer } from "./renderers/MenuElementRenderer";
import { List, ListItem } from "@webiny/ui/List";
import { MenuFooter, subFooter, MenuHeader, navHeader, navContent } from "./Styled";
import { config as appConfig } from "@webiny/app/config";
import { Typography } from "@webiny/ui/Typography";
import { List } from "@webiny/ui/List";
import { MenuFooter, MenuHeader, navContent, navHeader } from "./Styled";
import { WebinyVersionListItem } from "./WebinyVersionListItem";

const AutoWidthDrawer = styled(Drawer)`
width: auto;
Expand Down Expand Up @@ -93,8 +92,6 @@ export const NavigationImpl = () => {
[menuItems]
);

const wbyVersion = appConfig.getKey("WEBINY_VERSION", process.env.REACT_APP_WEBINY_VERSION);

return (
<AutoWidthDrawer modal open={visible} onClose={hideDrawer}>
<DrawerHeader className={navHeader}>
Expand All @@ -108,9 +105,7 @@ export const NavigationImpl = () => {
<MenuFooter>
<List nonInteractive>
<MenuItems menuItems={footerMenu} />
<ListItem ripple={false} className={subFooter}>
<Typography use={"body2"}>Webiny v{wbyVersion}</Typography>
</ListItem>
<WebinyVersionListItem />
</List>
</MenuFooter>
</AutoWidthDrawer>
Expand Down
3 changes: 2 additions & 1 deletion packages/app-admin/src/base/providers/TelemetryProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export const createTelemetryProvider = () => (Component: React.ComponentType) =>
}

eventSent = true;
sendEvent("app-start");

sendEvent("admin-app-start");
}, []);

return <Component>{children}</Component>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import get from "lodash/get";
import set from "lodash/set";
import { useMutation, useQuery } from "@apollo/react-hooks";
import { useSnackbar } from "@webiny/app-admin";
import { sendEvent, setProperties } from "@webiny/telemetry/react";
import { sendEvent } from "@webiny/telemetry/react";
import {
GET_SETTINGS,
GetSettingsQueryResponse,
Expand Down Expand Up @@ -69,20 +69,11 @@ export function usePbWebsiteSettings() {
// TODO: try useForm and onSubmit
data.websiteUrl = (data.websiteUrl || "").replace(/\/+$/g, "");

if (settings.websiteUrl !== data.websiteUrl && !data.websiteUrl.includes("localhost")) {
/**
* sendEvent is async, why is it not awaited?
*/
// TODO @pavel
sendEvent("custom-domain", {
domain: data.websiteUrl
});

/**
* setProperties is async, why is it not awaited?
*/
// TODO @pavel
setProperties({
const logWebsiteUrl =
settings.websiteUrl !== data.websiteUrl && !data.websiteUrl.includes("localhost");
if (logWebsiteUrl) {
// We don't want to await the result, so that we don't block the UI.
sendEvent("admin-custom-domain", {
domain: data.websiteUrl
});
}
Expand Down
2 changes: 2 additions & 0 deletions packages/app-wcp/src/WcpProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export const GET_WCP_PROJECT = gql`
wcp {
getProject {
data {
orgId
projectId
package {
features {
seats {
Expand Down
2 changes: 2 additions & 0 deletions packages/app-wcp/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export type WcpProjectPackage = {
};

export interface WcpProject {
orgId: string;
projectId: string;
package: WcpProjectPackage;
}

Expand Down
14 changes: 12 additions & 2 deletions packages/cli-plugin-deploy-pulumi/commands/build.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const buildPackages = require("./deploy/buildPackages");
const { PackagesBuilder } = require("./buildPackages/PackagesBuilder");
const { createPulumiCommand, runHook } = require("../utils");

module.exports = (params, context) => {
Expand All @@ -16,7 +16,17 @@ module.exports = (params, context) => {
context
});

await buildPackages({ projectApplication, inputs, context });
console.log();

const builder = new PackagesBuilder({
packages: projectApplication.packages,
inputs,
context
});

await builder.build();

console.log();

await runHook({
hook: "hook-after-build",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class BasePackagesBuilder {
constructor({ packages, inputs, context }) {
this.packages = packages;
this.inputs = inputs;
this.context = context;
}

async build() {
throw new Error("Not implemented.");
}
}

module.exports = { BasePackagesBuilder };
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
const path = require("path");
const { Worker } = require("worker_threads");
const Listr = require("listr");
const { BasePackagesBuilder } = require("./BasePackagesBuilder");
const { gray } = require("chalk");
const { measureDuration } = require("../../utils");

class MultiplePackagesBuilder extends BasePackagesBuilder {
async build() {
const packages = this.packages;
const context = this.context;
const inputs = this.inputs;

const getBuildDuration = measureDuration();

const { env, variant, debug } = inputs;

context.info(`Building %s packages...`, packages.length);

const buildTasks = [];

for (let i = 0; i < packages.length; i++) {
const pkg = packages[i];

buildTasks.push({
pkg: pkg,
task: new Promise((resolve, reject) => {
const enableLogs = inputs.logs === true;

const workerData = {
options: {
env,
variant,
debug,
logs: enableLogs
},
package: { ...pkg.paths }
};

const worker = new Worker(path.join(__dirname, "./worker.js"), {
workerData,
stderr: true,
stdout: true
});

worker.on("message", threadMessage => {
const { type, stdout, stderr, error } = JSON.parse(threadMessage);

const result = {
package: pkg,
stdout,
stderr,
error,
duration: getBuildDuration()
};

if (type === "error") {
reject(result);
return;
}

if (type === "success") {
resolve(result);
}
});
})
});
}

const tasks = new Listr(
buildTasks.map(({ pkg, task }) => {
return {
title: this.getPackageLabel(pkg),
task: () => task
};
}),
{ concurrent: true, exitOnError: false }
);

await tasks.run().catch(err => {
console.log();
context.error(`Failed to build all packages. For more details, check the logs below.`);
console.log();

err.errors.forEach(({ package: pkg, error }, i) => {
const number = `${i + 1}.`;
const name = context.error.hl(pkg.name);
const relativePath = gray(`(${pkg.paths.relative})`);
const title = [number, name, relativePath].join(" ");

console.log(title);
console.log(error.message);
console.log();
});

throw new Error(`Failed to build all packages.`);
});

console.log();

context.success(`Successfully built ${packages.length} packages in ${getBuildDuration()}.`);
}

getPackageLabel(pkg) {
const pkgName = pkg.name;
const pkgRelativePath = gray(`(${pkg.paths.relative})`);
return `${pkgName} ${pkgRelativePath}`;
}
}

module.exports = { MultiplePackagesBuilder };
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const { BasePackagesBuilder } = require("./BasePackagesBuilder");

class PackagesBuilder extends BasePackagesBuilder {
async build() {
const BuilderClass = this.getBuilderClass();

const builder = new BuilderClass({
packages: this.packages,
inputs: this.inputs,
context: this.context
});

await builder.build();
}

getBuilderClass() {
const packagesCount = this.packages.length;
if (packagesCount === 0) {
const { ZeroPackagesBuilder } = require("./ZeroPackagesBuilder");
return ZeroPackagesBuilder;
}

if (packagesCount === 1) {
const { SinglePackageBuilder } = require("./SinglePackageBuilder");
return SinglePackageBuilder;
}

const { MultiplePackagesBuilder } = require("./MultiplePackagesBuilder");
return MultiplePackagesBuilder;
}
}

module.exports = { PackagesBuilder };
Loading

0 comments on commit 16b0da1

Please sign in to comment.