Add cli
parent
40ad51381e
commit
3a3c3a918b
|
@ -40,7 +40,8 @@
|
|||
"embed-tests-quick": "turbo run embed-tests-quick",
|
||||
"embed-tests": "turbo run embed-tests",
|
||||
"test-e2e": "turbo run test-e2e --concurrency=1",
|
||||
"type-check": "turbo run type-check"
|
||||
"type-check": "turbo run type-check",
|
||||
"app-store": "yarn workspace @calcom/app-store-cli cli"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dotenv-checker": "^1.1.5",
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
dist
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"name": "@calcom/app-store-cli",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"bin": "dist/cli.js",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"build:watch": "tsc --watch",
|
||||
"build": "tsc && chmod +x dist/cli.js",
|
||||
"start": "npm run build && dist/cli.js",
|
||||
"pretest": "npm run build",
|
||||
"test": "xo && ava",
|
||||
"cli": "chmod +x dist/cli.js && dist/cli.js"
|
||||
},
|
||||
"files": [
|
||||
"dist/cli.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"ink": "^3.2.0",
|
||||
"ink-text-input": "^4.0.3",
|
||||
"meow": "^9.0.0",
|
||||
"react": "^17.0.2"
|
||||
},
|
||||
"ava": {
|
||||
"typescript": {
|
||||
"extensions": [
|
||||
"tsx"
|
||||
],
|
||||
"rewritePaths": {
|
||||
"source/": "dist/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"xo": {
|
||||
"extends": "xo-react",
|
||||
"rules": {
|
||||
"react/prop-types": "off"
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ava/typescript": "^3.0.1",
|
||||
"@sindresorhus/tsconfig": "^2.0.0",
|
||||
"@types/react": "^18.0.9",
|
||||
"ava": "^4.2.0",
|
||||
"chalk": "^4.1.2",
|
||||
"eslint-config-xo-react": "^0.27.0",
|
||||
"eslint-plugin-react": "^7.30.0",
|
||||
"eslint-plugin-react-hooks": "^4.5.0",
|
||||
"ink-testing-library": "^2.1.0",
|
||||
"typescript": "^4.6.4",
|
||||
"xo": "^0.39.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
## Steps to create an app
|
||||
|
||||
- Create a folder in packages/app-store/{APP_NAME} = {APP}
|
||||
- Fill it with a sample app
|
||||
- Modify {APP}/_metadata.ts with the data provided
|
||||
- ## package.json
|
||||
|
||||
Change name and description
|
||||
|
||||
**Variables**
|
||||
|
||||
**PREFIXES**:
|
||||
|
||||
CLI_BASE__
|
||||
|
||||
cli_base_
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env node
|
||||
import React from 'react';
|
||||
import {render} from 'ink';
|
||||
import meow from 'meow';
|
||||
import App from './ui';
|
||||
|
||||
const cli = meow(`
|
||||
Usage
|
||||
$ code
|
||||
|
||||
Options
|
||||
--bname Your name
|
||||
|
||||
Examples
|
||||
$ code --name=Jane
|
||||
Hello, Jane
|
||||
`, {
|
||||
flags: {
|
||||
name: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
render(<App name={cli.flags.name}/>);
|
|
@ -0,0 +1 @@
|
|||
export const calRepoPrefix = "/Users/hariombalhara/www/cal.com/"
|
|
@ -0,0 +1,17 @@
|
|||
import React from 'react';
|
||||
import chalk from 'chalk';
|
||||
import test from 'ava';
|
||||
import {render} from 'ink-testing-library';
|
||||
import App from './ui';
|
||||
|
||||
test('greet unknown user', t => {
|
||||
const {lastFrame} = render(<App/>);
|
||||
|
||||
t.is(lastFrame(), chalk`Hello, {green Stranger}`);
|
||||
});
|
||||
|
||||
test('greet user with a name', t => {
|
||||
const {lastFrame} = render(<App name="Jane"/>);
|
||||
|
||||
t.is(lastFrame(), chalk`Hello, {green Jane}`);
|
||||
});
|
|
@ -0,0 +1,104 @@
|
|||
import child_process from "child_process";
|
||||
import fs from "fs";
|
||||
import { Box, Text, useApp, useInput, useStdin } from "ink";
|
||||
import TextInput from "ink-text-input";
|
||||
import React, { FC, useEffect, useRef, useState } from "react";
|
||||
|
||||
const InputAppDetails = () => {
|
||||
// AppName
|
||||
// Type of App - Other, Calendar, Video, Payment, Messaging, Web3
|
||||
const [appInputData, setAppInputData] = useState({});
|
||||
const [inputIndex, setInputIndex] = useState(0);
|
||||
const fields = [
|
||||
{ label: "App Name", name: "appName" },
|
||||
{ label: "Type of App", name: "appType" },
|
||||
];
|
||||
const fieldLabel = fields[inputIndex]?.label || "";
|
||||
const fieldName = fields[inputIndex]?.name || "";
|
||||
const fieldValue = appInputData[fieldName] || "";
|
||||
const appName = appInputData["appName"];
|
||||
const appType = appInputData["appType"];
|
||||
const [result, setResult] = useState("...");
|
||||
useEffect(() => {
|
||||
if (inputIndex === fields.length) {
|
||||
let config = {
|
||||
name: appName,
|
||||
type: appType,
|
||||
slug: appName,
|
||||
};
|
||||
const appDirPath = `packages/app-store/${appName}/`;
|
||||
child_process.execSync(
|
||||
`mkdir -p ${appDirPath} && cp -r packages/app-store/CLI_BASE__APP_NAME/* ${appDirPath}`
|
||||
);
|
||||
|
||||
const packageJsonConfig = JSON.parse(fs.readFileSync(`${appDirPath}/package.json`).toString());
|
||||
packageJsonConfig.name = `@calcom/${appName}`;
|
||||
// packageJsonConfig.description = `@calcom/${appName}`;
|
||||
fs.writeFileSync(`${appDirPath}/package.json`, JSON.stringify(packageJsonConfig, null, 2));
|
||||
|
||||
const baseConfig = JSON.parse(fs.readFileSync(`${appDirPath}/config.json`).toString());
|
||||
config = {
|
||||
...baseConfig,
|
||||
...config,
|
||||
};
|
||||
fs.writeFileSync(`${appDirPath}/config.json`, JSON.stringify(config, null, 2));
|
||||
|
||||
const seedConfig = JSON.parse(fs.readFileSync(`packages/prisma/seed-app-store.config.json`).toString());
|
||||
if (!seedConfig.find((app) => app.name === appName)) {
|
||||
seedConfig.push({
|
||||
name: appName,
|
||||
dirName: appName,
|
||||
categories: [appType],
|
||||
type: `${appName}_${appType}`,
|
||||
});
|
||||
}
|
||||
|
||||
fs.writeFileSync(`packages/prisma/seed-app-store.config.json`, JSON.stringify(seedConfig, null, 2));
|
||||
child_process.execSync(`yarn db-seed`);
|
||||
child_process.execSync(`cd packages/app-store && node generate-apps.js`);
|
||||
|
||||
setResult("App Generated");
|
||||
}
|
||||
});
|
||||
if (inputIndex === fields.length) {
|
||||
return (
|
||||
<>
|
||||
<Text>
|
||||
Creating app with name "{appName}" of type "{appType}"
|
||||
</Text>
|
||||
<Text>{result}</Text>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Box>
|
||||
<Text color="green">{`${fieldLabel}:`}</Text>
|
||||
<TextInput
|
||||
value={fieldValue}
|
||||
onSubmit={(value) => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
setInputIndex((index) => {
|
||||
return index + 1;
|
||||
});
|
||||
}}
|
||||
onChange={(value) => {
|
||||
if (value) {
|
||||
value = value.replace(/-/g, "_");
|
||||
}
|
||||
setAppInputData((appInputData) => {
|
||||
return {
|
||||
...appInputData,
|
||||
[fieldName]: value,
|
||||
};
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const App: FC<{ name?: string }> = () => <InputAppDetails />;
|
||||
module.exports = App;
|
||||
export default App;
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": "@sindresorhus/tsconfig",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"jsx": "react",
|
||||
"esModuleInterop": true,
|
||||
"outDir": "dist",
|
||||
"noEmitOnError": false
|
||||
},
|
||||
"include": ["source"]
|
||||
}
|
|
@ -1,5 +1,9 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
import type { App } from "@calcom/types/App";
|
||||
|
||||
import config from "./config.json";
|
||||
import _package from "./package.json";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
|
@ -21,6 +25,7 @@ export const metadata = {
|
|||
variant: "CLI_BASE__APP_TYPE",
|
||||
verified: true,
|
||||
email: "CLI_BASE__PUBLISHER_EMAIL",
|
||||
...config,
|
||||
} as App;
|
||||
|
||||
export default metadata;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -0,0 +1,10 @@
|
|||
[
|
||||
{
|
||||
"name": "zoom1app",
|
||||
"dirName": "zoom1app",
|
||||
"categories": [
|
||||
"other"
|
||||
],
|
||||
"type": "zoom1app_other"
|
||||
}
|
||||
]
|
|
@ -1,9 +0,0 @@
|
|||
const generatedApps = [
|
||||
{
|
||||
name: "CLI_BASE__APP_NAME",
|
||||
dirName: "CLI_BASE__APP_NAME",
|
||||
categories: ["other"],
|
||||
type: "CLI_BASE_APP_NAME_CLI_BASE_APP_TYPE",
|
||||
},
|
||||
];
|
||||
export default generatedApps;
|
|
@ -1,7 +1,8 @@
|
|||
import { Prisma } from "@prisma/client";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
import prisma from ".";
|
||||
import generatedApps from "./seed-app-store.config";
|
||||
|
||||
require("dotenv").config({ path: "../../.env.appStore" });
|
||||
|
||||
|
@ -132,6 +133,10 @@ async function main() {
|
|||
webhook_secret: process.env.STRIPE_WEBHOOK_SECRET,
|
||||
});
|
||||
}
|
||||
|
||||
const generatedApps = JSON.parse(
|
||||
fs.readFileSync(path.join(__dirname, "seed-app-store.config.json"), "utf8")
|
||||
);
|
||||
for (let i = 0; i < generatedApps.length; i++) {
|
||||
const generatedApp = generatedApps[i];
|
||||
await createApp(generatedApp.name, generatedApp.dirName, generatedApp.categories, generatedApp.type);
|
||||
|
|
Loading…
Reference in New Issue