Skip to content

Commit

Permalink
Improvement/AppStore: Remove seeding from app-store-cli. (calcom#8486)
Browse files Browse the repository at this point in the history
* Remove seeding from cli

* Self review fixes

* Fix TS error
  • Loading branch information
hariombalhara authored May 12, 2023
1 parent 607ef71 commit ff85973
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 80 deletions.
61 changes: 48 additions & 13 deletions apps/web/pages/apps/[slug]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fs from "fs";
import matter from "gray-matter";
import MarkdownIt from "markdown-it";
import type { GetStaticPaths, GetStaticPropsContext } from "next";
import Link from "next/link";
import path from "path";
import { z } from "zod";

Expand Down Expand Up @@ -33,7 +34,26 @@ const sourceSchema = z.object({
}),
});

function SingleAppPage({ data, source }: inferSSRProps<typeof getStaticProps>) {
function SingleAppPage(props: inferSSRProps<typeof getStaticProps>) {
// If it's not production environment, it would be a better idea to inform that the App is disabled.
if (props.isAppDisabled) {
if (process.env.NODE_ENV !== "production") {
// TODO: Improve disabled App UI. This is just a placeholder.
return (
<div className="p-2">
This App seems to be disabled. If you are an admin, you can enable this app from{" "}
<Link href="/settings/admin/apps" className="cursor-pointer text-blue-500 underline">
here
</Link>
</div>
);
}

// Disabled App should give 404 any ways in production.
return null;
}

const { source, data } = props;
return (
<App
name={data.name}
Expand Down Expand Up @@ -80,29 +100,43 @@ export const getStaticPaths: GetStaticPaths<{ slug: string }> = async () => {
export const getStaticProps = async (ctx: GetStaticPropsContext) => {
if (typeof ctx.params?.slug !== "string") return { notFound: true };

const app = await prisma.app.findUnique({
where: { slug: ctx.params.slug.toLowerCase() },
const appMeta = await getAppWithMetadata({
slug: ctx.params?.slug,
});

if (!app) return { notFound: true };
const appFromDb = await prisma.app.findUnique({
where: { slug: ctx.params.slug.toLowerCase() },
});

const singleApp = await getAppWithMetadata(app);
const isAppAvailableInFileSystem = appMeta;
const isAppDisabled = isAppAvailableInFileSystem && (!appFromDb || !appFromDb.enabled);

if (process.env.NODE_ENV !== "production" && isAppDisabled) {
return {
props: {
isAppDisabled: true as const,
data: {
...appMeta,
},
},
};
}

if (!singleApp) return { notFound: true };
if (!appFromDb || !appMeta || isAppDisabled) return { notFound: true };

const isTemplate = singleApp.isTemplate;
const appDirname = path.join(isTemplate ? "templates" : "", app.dirName);
const isTemplate = appMeta.isTemplate;
const appDirname = path.join(isTemplate ? "templates" : "", appFromDb.dirName);
const README_PATH = path.join(process.cwd(), "..", "..", `packages/app-store/${appDirname}/DESCRIPTION.md`);
const postFilePath = path.join(README_PATH);
let source = "";

try {
source = fs.readFileSync(postFilePath).toString();
source = source.replace(/{DESCRIPTION}/g, singleApp.description);
source = source.replace(/{DESCRIPTION}/g, appMeta.description);
} catch (error) {
/* If the app doesn't have a README we fallback to the package description */
console.log(`No DESCRIPTION.md provided for: ${appDirname}`);
source = singleApp.description;
source = appMeta.description;
}

const result = matter(source);
Expand All @@ -111,17 +145,18 @@ export const getStaticProps = async (ctx: GetStaticPropsContext) => {
data.items = data.items.map((item) => {
if (typeof item === "string") {
return getAppAssetFullPath(item, {
dirName: singleApp.dirName,
isTemplate: singleApp.isTemplate,
dirName: appMeta.dirName,
isTemplate: appMeta.isTemplate,
});
}
return item;
});
}
return {
props: {
isAppDisabled: false as const,
source: { content, data },
data: singleApp,
data: appMeta,
},
};
};
Expand Down
10 changes: 6 additions & 4 deletions packages/app-store-cli/src/components/AppCreateUpdateForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import SelectInput from "ink-select-input";
import TextInput from "ink-text-input";
import React, { useEffect, useState } from "react";

import { AppMeta } from "@calcom/types/App";
import type { AppMeta } from "@calcom/types/App";

import { getSlugFromAppName, BaseAppFork, Seed, generateAppFiles, getAppDirPath } from "../core";
import { getSlugFromAppName, BaseAppFork, generateAppFiles, getAppDirPath } from "../core";
import { getApp } from "../utils/getApp";
import Templates from "../utils/templates";
import Label from "./Label";
Expand Down Expand Up @@ -148,8 +148,6 @@ export const AppForm = ({
oldSlug: givenSlug,
});

await Seed.update({ slug, category: category, oldSlug: givenSlug, isTemplate });

await generateAppFiles();

// FIXME: Even after CLI showing this message, it is stuck doing work before exiting
Expand Down Expand Up @@ -242,6 +240,10 @@ export const AppForm = ({
<Text color="green">Publisher Email: </Text>
<Text>{email}</Text>
</Box>
<Text bold>
Next Step: Enable the app from http://localhost:3000/settings/admin/apps as admin user (Email:
[email protected], Pass: ADMINadmin2022!)
</Text>
</Box>
</Box>
)}
Expand Down
3 changes: 1 addition & 2 deletions packages/app-store-cli/src/components/DeleteForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React, { useEffect, useState } from "react";

import { ImportantText } from "../components/ImportantText";
import { Message } from "../components/Message";
import { BaseAppFork, Seed, generateAppFiles } from "../core";
import { BaseAppFork, generateAppFiles } from "../core";
import { getApp } from "../utils/getApp";

export default function DeleteForm({ slug, action }: { slug: string; action: "delete" | "delete-template" }) {
Expand All @@ -28,7 +28,6 @@ export default function DeleteForm({ slug, action }: { slug: string; action: "de
if (state === "DELETION_CONFIRMATION_SUCCESSFUL") {
(async () => {
await BaseAppFork.delete({ slug, isTemplate });
Seed.revert({ slug });
await generateAppFiles();
// successMsg({ text: `App with slug ${slug} has been deleted`, done: true });
setState("DELETION_COMPLETED");
Expand Down
58 changes: 0 additions & 58 deletions packages/app-store-cli/src/core.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import fs from "fs";
import path from "path";

import type seedAppStoreConfig from "@calcom/prisma/seed-app-store.config.json";

import { APP_STORE_PATH, TEMPLATES_PATH } from "./constants";
import execSync from "./utils/execSync";

Expand All @@ -27,10 +25,6 @@ export function getAppDirPath(slug: string, isTemplate: boolean) {
return path.join(TEMPLATES_PATH, `${slug}`);
}

function absolutePath(appRelativePath: string) {
return path.join(APP_STORE_PATH, appRelativePath);
}

const updatePackageJson = ({
slug,
appDescription,
Expand Down Expand Up @@ -138,58 +132,6 @@ export const BaseAppFork = {
},
};

export const Seed = {
seedConfigPath: absolutePath("../prisma/seed-app-store.config.json"),
update: async function ({
slug,
category,
oldSlug,
isTemplate,
}: {
slug: string;
category: string;
oldSlug: string;
isTemplate: boolean;
}) {
let configContent = "[]";
try {
if (fs.statSync(this.seedConfigPath)) {
configContent = fs.readFileSync(this.seedConfigPath).toString();
}
} catch (e) {}

let seedConfig: typeof seedAppStoreConfig = JSON.parse(configContent);
seedConfig = seedConfig.filter((app) => app.slug !== oldSlug);

if (!seedConfig.find((app) => app.slug === slug)) {
seedConfig.push({
dirName: slug,
categories: [category],
slug: slug,
type: `${slug}_${category}`,
isTemplate: isTemplate,
});
}

// Add the message as a property to first item so that it stays always at the top
seedConfig[0]["/*"] =
"This file is auto-generated and updated by `yarn app-store create/edit`. Don't edit it manually";

// Add the message as a property to first item so that it stays always at the top
seedConfig[0]["/*"] =
"This file is auto-generated and updated by `yarn app-store create/edit`. Don't edit it manually";

fs.writeFileSync(this.seedConfigPath, JSON.stringify(seedConfig, null, 2));
await execSync(`cd ${workspaceDir}/packages/prisma && yarn seed-app-store seed-templates`);
},
revert: async function ({ slug }: { slug: string }) {
let seedConfig: typeof seedAppStoreConfig = JSON.parse(fs.readFileSync(this.seedConfigPath).toString());
seedConfig = seedConfig.filter((app) => app.slug !== slug);
fs.writeFileSync(this.seedConfigPath, JSON.stringify(seedConfig, null, 2));
await execSync(`yarn workspace @calcom/prisma delete-app ${slug}`);
},
};

export const generateAppFiles = async () => {
await execSync(`yarn ts-node --transpile-only src/build.ts`);
};
18 changes: 16 additions & 2 deletions packages/app-store/_appRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,22 @@ import { userMetadata } from "@calcom/prisma/zod-utils";
import type { AppFrontendPayload as App } from "@calcom/types/App";
import type { CredentialFrontendPayload as Credential } from "@calcom/types/Credential";

export async function getAppWithMetadata(app: { dirName: string }) {
const appMetadata: App | null = appStoreMetadata[app.dirName as keyof typeof appStoreMetadata] as App;
/**
* Get App metdata either using dirName or slug
*/
export async function getAppWithMetadata(app: { dirName: string } | { slug: string }) {
let appMetadata: App | null;

if ("dirName" in app) {
appMetadata = appStoreMetadata[app.dirName as keyof typeof appStoreMetadata] as App;
} else {
const foundEntry = Object.entries(appStoreMetadata).find(([, meta]) => {
return meta.slug === app.slug;
});
if (!foundEntry) return null;
appMetadata = foundEntry[1] as App;
}

if (!appMetadata) return null;
// Let's not leak api keys to the front end
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down
2 changes: 1 addition & 1 deletion packages/prisma/seed-app-store.config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"/*": "This file is auto-generated and updated by `yarn app-store create/edit`. Don't edit it manually",
"/*": "This file is deprecated now. No new entry should be added to it.",
"dirName": "routing-forms",
"categories": ["other"],
"slug": "routing-forms",
Expand Down
4 changes: 4 additions & 0 deletions packages/prisma/seed-app-store.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @deprecated
* This file is deprecated. The only use of this file is to seed the database for E2E tests. Each test should take care of seeding it's own data going forward.
*/
import type { Prisma } from "@prisma/client";
import dotEnv from "dotenv";
import fs from "fs";
Expand Down

0 comments on commit ff85973

Please sign in to comment.