Cleanup CI workflows, Remove Twenty CLI, Add Danger.js (#2452)
* Move dockerignore file away from root * Delete Twenty CLI * Create Twenty-utils * Move release script * Add danger.js to yarn * Add danger * Add Bot token * Cancel previous steps CI * Revert "Move dockerignore file away from root" This reverts commit 7ed17bb2bcccd3312a455d35974c9c388687a0a9.
This commit is contained in:
2
.github/workflows/cd-deploy-main.yaml
vendored
2
.github/workflows/cd-deploy-main.yaml
vendored
@ -1,4 +1,4 @@
|
||||
name: CD deply main
|
||||
name: CD deploy main
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
|
||||
15
.github/workflows/ci-docs.yaml
vendored
15
.github/workflows/ci-docs.yaml
vendored
@ -21,3 +21,18 @@ jobs:
|
||||
run: cd docs && yarn
|
||||
- name: Docs / Build Documentation
|
||||
run: cd docs && yarn build
|
||||
vale:
|
||||
name: runner / vale
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: errata-ai/vale-action@reviewdog
|
||||
with:
|
||||
files: ${{ steps.directories.outputs.LIST }}
|
||||
fail_on_error: true
|
||||
vale_flags: '--minAlertLevel=error'
|
||||
reporter: github-pr-check
|
||||
token: ${{ github.token }}
|
||||
filter_mode: nofilter
|
||||
env:
|
||||
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
|
||||
26
.github/workflows/ci-utils.yaml
vendored
Normal file
26
.github/workflows/ci-utils.yaml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: CI Utils
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
jobs:
|
||||
danger-js:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18"
|
||||
- name: Utils / Install Dependencies
|
||||
run: cd packages/twenty-utils && yarn
|
||||
- name: Utils / Run Danger.js
|
||||
run: cd packages/twenty-utils && yarn danger ci
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.TOKEN_FOR_GITHUB_BOT }}
|
||||
|
||||
22
.github/workflows/ci-vale.yaml
vendored
22
.github/workflows/ci-vale.yaml
vendored
@ -1,22 +0,0 @@
|
||||
name: CI-Vale
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
jobs:
|
||||
vale:
|
||||
name: runner / vale
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: errata-ai/vale-action@reviewdog
|
||||
with:
|
||||
files: ${{ steps.directories.outputs.LIST }}
|
||||
fail_on_error: true
|
||||
vale_flags: '--minAlertLevel=error'
|
||||
reporter: github-pr-check
|
||||
token: ${{ github.token }}
|
||||
filter_mode: nofilter
|
||||
env:
|
||||
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
|
||||
@ -1,9 +1,5 @@
|
||||
{
|
||||
"name": "twenty",
|
||||
"scripts": {
|
||||
"release": "node infra/release/release.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": "^7.5.4"
|
||||
"devDependencies": {
|
||||
"danger": "^11.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.json',
|
||||
tsconfigRootDir: __dirname,
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['@typescript-eslint/eslint-plugin'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:prettier/recommended'
|
||||
],
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
jest: true,
|
||||
},
|
||||
ignorePatterns: ['.eslintrc.js', 'codegen.js', '**/generated/*', '/lib/*'],
|
||||
rules: {
|
||||
'@typescript-eslint/interface-name-prefix': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
"@typescript-eslint/consistent-type-imports": ["error", { "prefer": "no-type-imports" }],
|
||||
},
|
||||
};
|
||||
|
||||
36
packages/twenty-cli/.gitignore
vendored
36
packages/twenty-cli/.gitignore
vendored
@ -1,36 +0,0 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# other
|
||||
lib/
|
||||
.DS_Store
|
||||
@ -1,4 +0,0 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
# Twenty CLI
|
||||
A simple CLI to get started with Twenty
|
||||
@ -1,8 +0,0 @@
|
||||
import { execShell } from '../src/config';
|
||||
|
||||
export {};
|
||||
|
||||
test('execShell runs a shell command', async () => {
|
||||
let response = await execShell('echo "hello"');
|
||||
expect(response).toEqual('hello\n');
|
||||
});
|
||||
@ -1,5 +0,0 @@
|
||||
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
};
|
||||
5872
packages/twenty-cli/package-lock.json
generated
5872
packages/twenty-cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,41 +0,0 @@
|
||||
{
|
||||
"name": "twenty-cli",
|
||||
"version": "1.0.5",
|
||||
"type": "module",
|
||||
"description": "A simple CLI to install and interact with Twenty",
|
||||
"files": [
|
||||
"!lib/__tests__/**/*",
|
||||
"lib/**/*",
|
||||
"bin/**/*"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/gradient-string": "^1.1.2",
|
||||
"chalk": "^5.2.0",
|
||||
"commander": "^10.0.1",
|
||||
"dotenv": "^16.1.1",
|
||||
"gradient-string": "^2.0.2",
|
||||
"open": "^9.1.0",
|
||||
"pg": "^8.11.0",
|
||||
"prompts": "^2.4.2"
|
||||
},
|
||||
"bin": {
|
||||
"twenty": "./lib/index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.1",
|
||||
"@types/node": "^20.2.5",
|
||||
"@types/pg": "^8.10.1",
|
||||
"@types/prompts": "^2.4.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.8",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"jest": "^29.5.0",
|
||||
"ts-jest": "^29.1.0",
|
||||
"typescript": "^5.0.4"
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
import { exec } from 'child_process';
|
||||
|
||||
export const execShell = (cmd: string): Promise<string> =>
|
||||
new Promise((resolve, reject) => {
|
||||
exec(cmd, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.warn(`Error: ${error.message}`);
|
||||
console.warn(`stderr: ${stderr}`);
|
||||
reject(error);
|
||||
}
|
||||
resolve(stdout ? stdout : stderr);
|
||||
});
|
||||
});
|
||||
|
||||
export const REPO_URL = 'https://github.com/twentyhq/twenty.git';
|
||||
export const CLONE_DIR = 'twenty';
|
||||
@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
import { program } from 'commander';
|
||||
import { showWelcomeScreen, firstQuestion } from './install/index.js';
|
||||
import prompts from 'prompts';
|
||||
import { askContributeQuestions } from './install/contribute/index.js';
|
||||
import { askDemoQuestions } from './install/demo/index.js';
|
||||
import { askSelfhostQuestions } from './install/selfhost/index.js';
|
||||
|
||||
program;
|
||||
|
||||
showWelcomeScreen();
|
||||
|
||||
(async () => {
|
||||
const response = await prompts(firstQuestion);
|
||||
|
||||
switch (response.install_type) {
|
||||
case 'contribute':
|
||||
askContributeQuestions();
|
||||
break;
|
||||
case 'demo':
|
||||
askDemoQuestions();
|
||||
break;
|
||||
case 'selfhost':
|
||||
askSelfhostQuestions();
|
||||
break;
|
||||
}
|
||||
})();
|
||||
@ -1,35 +0,0 @@
|
||||
import prompts, { PromptObject } from 'prompts';
|
||||
import { askContributeLocalQuestions } from './local/index.js';
|
||||
import { askContributeRemoteQuestions } from './remote.js';
|
||||
|
||||
export const contributeQuestions: PromptObject<string>[] = [
|
||||
{
|
||||
type: 'select',
|
||||
name: 'contribute_type',
|
||||
message: 'Where do you want to setup your development environment?',
|
||||
choices: [
|
||||
{
|
||||
title: 'Local',
|
||||
description: 'I want to setup a development environment on my machine',
|
||||
value: 'local',
|
||||
},
|
||||
{
|
||||
title: 'Remote (via Github Codespaces)',
|
||||
description: 'A simple pre-configured remote environment',
|
||||
value: 'remote',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const askContributeQuestions: () => Promise<void> = async () => {
|
||||
const response = await prompts(contributeQuestions);
|
||||
switch (response.contribute_type) {
|
||||
case 'local':
|
||||
await askContributeLocalQuestions();
|
||||
break;
|
||||
case 'remote':
|
||||
await askContributeRemoteQuestions();
|
||||
break;
|
||||
}
|
||||
};
|
||||
@ -1,128 +0,0 @@
|
||||
import prompts, { PromptObject } from 'prompts';
|
||||
import { spawn } from 'child_process';
|
||||
import { execShell, REPO_URL } from '../../../config.js';
|
||||
import { join } from 'path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
export const dockerQuestions: PromptObject<string>[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'folder_name',
|
||||
initial: 'twenty',
|
||||
message: 'Name of folder where we will clone the repo?',
|
||||
},
|
||||
];
|
||||
|
||||
export const askDockerQuestions: () => Promise<void> = async () => {
|
||||
let folderResponse = await prompts(dockerQuestions);
|
||||
|
||||
let folderExists = fs.existsSync(folderResponse.folder_name);
|
||||
while (folderExists) {
|
||||
try {
|
||||
folderResponse = await prompts({
|
||||
type: 'text',
|
||||
name: 'folder_name',
|
||||
message:
|
||||
'Folder already exists. Please choose another name and press enter.',
|
||||
});
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.Signals) === 'SIGINT') {
|
||||
process.exit(0);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
folderExists = fs.existsSync(folderResponse.folder_name);
|
||||
}
|
||||
|
||||
let git_is_installed = false;
|
||||
while (!git_is_installed) {
|
||||
try {
|
||||
await execShell('git --version');
|
||||
git_is_installed = true;
|
||||
} catch (error) {
|
||||
try {
|
||||
await prompts({
|
||||
type: 'text',
|
||||
name: 'git_install',
|
||||
message:
|
||||
'Git does not appear to be installed. Please install it and press enter.',
|
||||
});
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.Signals) === 'SIGINT') {
|
||||
process.exit(0);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let docker_is_installed = false;
|
||||
while (!docker_is_installed) {
|
||||
try {
|
||||
await execShell('docker --version');
|
||||
docker_is_installed = true;
|
||||
} catch (error) {
|
||||
try {
|
||||
await prompts({
|
||||
type: 'text',
|
||||
name: 'docker_install',
|
||||
message:
|
||||
'Docker does not appear to be installed. Please install it and press enter.',
|
||||
});
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.Signals) === 'SIGINT') {
|
||||
process.exit(0);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let docker_daemon_running = false;
|
||||
while (!docker_daemon_running) {
|
||||
try {
|
||||
await execShell('docker info');
|
||||
docker_daemon_running = true;
|
||||
} catch (error) {
|
||||
try {
|
||||
await prompts({
|
||||
type: 'text',
|
||||
name: 'docker_install',
|
||||
message:
|
||||
'Docker daemon does not appear to be running. Please start it manually and press enter.',
|
||||
});
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.Signals) === 'SIGINT') {
|
||||
process.exit(0);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Cloning the Twenty repo. This can take a little while.');
|
||||
|
||||
await execShell(`git clone ${REPO_URL} ${folderResponse.folder_name}`);
|
||||
|
||||
console.log('Build the docker images. (cd infra/dev then make build)');
|
||||
|
||||
const makeBuild = spawn('make', ['build'], {
|
||||
cwd: join(folderResponse.folder_name, 'infra', 'dev'),
|
||||
});
|
||||
makeBuild.stdout.on('data', (data) => {
|
||||
console.log(`stdout: ${data}`);
|
||||
});
|
||||
makeBuild.stderr.on('data', (data) => {
|
||||
console.log(`stderr: ${data}`);
|
||||
});
|
||||
makeBuild.on('error', (error) => {
|
||||
console.log(`error: ${error.message}`);
|
||||
});
|
||||
makeBuild.on('close', (code) => {
|
||||
console.log(`child process exited with code ${code}`);
|
||||
});
|
||||
};
|
||||
@ -1,35 +0,0 @@
|
||||
import prompts, { PromptObject } from 'prompts';
|
||||
import { askDockerQuestions } from './docker.js';
|
||||
import { askNoDockerQuestions } from './no-docker.js';
|
||||
|
||||
export const contributeLocalQuestions: PromptObject<string>[] = [
|
||||
{
|
||||
type: 'select',
|
||||
name: 'local_setup_type',
|
||||
message: 'What is your prefered setup?',
|
||||
choices: [
|
||||
{
|
||||
title: 'Docker',
|
||||
description: 'A managed development environment with Postgres included',
|
||||
value: 'docker',
|
||||
},
|
||||
{
|
||||
title: 'Without docker',
|
||||
description: "You'll need to setup a Postgres instance on your own",
|
||||
value: 'no-docker',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const askContributeLocalQuestions: () => Promise<void> = async () => {
|
||||
const response = await prompts(contributeLocalQuestions);
|
||||
switch (response.local_setup_type) {
|
||||
case 'docker':
|
||||
await askDockerQuestions();
|
||||
break;
|
||||
case 'no-docker':
|
||||
await askNoDockerQuestions();
|
||||
break;
|
||||
}
|
||||
};
|
||||
@ -1,213 +0,0 @@
|
||||
import prompts, { PromptObject } from 'prompts';
|
||||
import { spawn } from 'child_process';
|
||||
import { execShell, REPO_URL } from '../../../config.js';
|
||||
import { join } from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import pkg from 'pg';
|
||||
const { Client } = pkg;
|
||||
|
||||
export const noDockerQuestion1: PromptObject<string>[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'folder_name',
|
||||
initial: 'twenty',
|
||||
message: 'Name of folder where we will clone the repo?',
|
||||
},
|
||||
];
|
||||
|
||||
export const noDockerQuestion2: PromptObject<string>[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'postgres_string',
|
||||
initial: 'postgres://twenty:twenty@postgres:5432/default',
|
||||
message:
|
||||
'Since you are not using Docker, you need to bring your own database, please enter your postgres connection string.',
|
||||
},
|
||||
];
|
||||
|
||||
export const askNoDockerQuestions: () => Promise<void> = async () => {
|
||||
let folderResponse = await prompts(noDockerQuestion1);
|
||||
|
||||
let folderExists = fs.existsSync(folderResponse.folder_name);
|
||||
while (folderExists) {
|
||||
try {
|
||||
folderResponse = await prompts({
|
||||
type: 'text',
|
||||
name: 'folder_name',
|
||||
message:
|
||||
'Folder already exists. Please choose another name and press enter.',
|
||||
});
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.Signals) === 'SIGINT') {
|
||||
process.exit(0);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
folderExists = fs.existsSync(folderResponse.folder_name);
|
||||
}
|
||||
|
||||
let connectionStringResponse = await prompts(noDockerQuestion2);
|
||||
|
||||
let postgres_connection_valid = false;
|
||||
while (!postgres_connection_valid) {
|
||||
const client = new Client({
|
||||
connectionString: connectionStringResponse.postgres_string,
|
||||
});
|
||||
try {
|
||||
await client.connect();
|
||||
await client.end();
|
||||
postgres_connection_valid = true;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
postgres_connection_valid = false;
|
||||
}
|
||||
if (!postgres_connection_valid) {
|
||||
try {
|
||||
connectionStringResponse = await prompts({
|
||||
type: 'text',
|
||||
name: 'postgres_string',
|
||||
initial: 'postgres://twenty:twenty@postgres:5432/default',
|
||||
message:
|
||||
'Connection to Postgres failed. Please enter the string again',
|
||||
});
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.Signals) === 'SIGINT') {
|
||||
process.exit(0);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let git_is_installed = false;
|
||||
while (!git_is_installed) {
|
||||
try {
|
||||
await execShell('git --version');
|
||||
git_is_installed = true;
|
||||
} catch (error) {
|
||||
try {
|
||||
await prompts({
|
||||
type: 'text',
|
||||
name: 'git_install',
|
||||
message:
|
||||
'Git does not appear to be installed. Please install it and restart.',
|
||||
});
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.Signals) === 'SIGINT') {
|
||||
process.exit(0);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let npm_is_installed = false;
|
||||
while (!npm_is_installed) {
|
||||
try {
|
||||
await execShell('npm --version');
|
||||
npm_is_installed = true;
|
||||
} catch (error) {
|
||||
try {
|
||||
await prompts({
|
||||
type: 'text',
|
||||
name: 'git_install',
|
||||
message:
|
||||
'Npm does not appear to be installed. Please install it and press enter.',
|
||||
});
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.Signals) === 'SIGINT') {
|
||||
process.exit(0);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Cloning the Twenty repo. This can take a little while.');
|
||||
|
||||
await execShell(`git clone ${REPO_URL} ${folderResponse.folder_name}`);
|
||||
|
||||
await execShell(
|
||||
`cp ${folderResponse.folder_name}/front/.env.example ${folderResponse.folder_name}/front/.env`,
|
||||
);
|
||||
await execShell(
|
||||
`cp ${folderResponse.folder_name}/server/.env.example ${folderResponse.folder_name}/server/.env`,
|
||||
);
|
||||
|
||||
const envFile = path.resolve(
|
||||
join(folderResponse.folder_name, 'server', '.env'),
|
||||
);
|
||||
let envFileLines = fs.readFileSync(envFile, 'utf-8').split('\n');
|
||||
envFileLines = envFileLines.map((line) =>
|
||||
line.startsWith('PG_DATABASE_URL=')
|
||||
? `PG_DATABASE_URL=${connectionStringResponse.postgres_string}`
|
||||
: line,
|
||||
);
|
||||
// write the updated content back to the .env file
|
||||
fs.writeFileSync(envFile, envFileLines.join('\n'));
|
||||
|
||||
console.log('Building the frontend (running npm install on frontend folder)');
|
||||
const buildFront = spawn('npm', ['install'], {
|
||||
cwd: join(folderResponse.folder_name, 'front'),
|
||||
});
|
||||
buildFront.stdout.on('data', (data) => {
|
||||
console.log(`${data}`);
|
||||
});
|
||||
buildFront.stderr.on('data', (data) => {
|
||||
console.log(`${data}`);
|
||||
});
|
||||
buildFront.on('error', (error) => {
|
||||
console.log(`error: ${error.message}`);
|
||||
});
|
||||
buildFront.on('close', () => {
|
||||
console.log('Building the server (running npm install on server folder)');
|
||||
const buildServer = spawn('npm', ['install'], {
|
||||
cwd: join(folderResponse.folder_name, 'server'),
|
||||
});
|
||||
buildServer.stdout.on('data', (data) => {
|
||||
console.log(`${data}`);
|
||||
});
|
||||
buildServer.stderr.on('data', (data) => {
|
||||
console.log(`${data}`);
|
||||
});
|
||||
buildServer.on('error', (error) => {
|
||||
console.log(`error: ${error.message}`);
|
||||
});
|
||||
buildServer.on('close', () => {
|
||||
console.log(
|
||||
'Running the frontend (running npm start on frontend folder)',
|
||||
);
|
||||
const runFrontend = spawn('npm', ['run', 'start'], {
|
||||
cwd: join(folderResponse.folder_name, 'server'),
|
||||
});
|
||||
runFrontend.stdout.on('data', (data) => {
|
||||
console.log(`${data}`);
|
||||
});
|
||||
runFrontend.stderr.on('data', (data) => {
|
||||
console.log(`${data}`);
|
||||
});
|
||||
runFrontend.on('error', (error) => {
|
||||
console.log(`error: ${error.message}`);
|
||||
});
|
||||
|
||||
console.log('Running the server (running npm start on server folder)');
|
||||
const runServer = spawn('npm', ['run', 'start'], {
|
||||
cwd: join(folderResponse.folder_name, 'server'),
|
||||
});
|
||||
runServer.stdout.on('data', (data) => {
|
||||
console.log(`${data}`);
|
||||
});
|
||||
runServer.stderr.on('data', (data) => {
|
||||
console.log(`${data}`);
|
||||
});
|
||||
runServer.on('error', (error) => {
|
||||
console.log(`error: ${error.message}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -1,16 +0,0 @@
|
||||
import prompts, { PromptObject } from 'prompts';
|
||||
import open from 'open';
|
||||
|
||||
export const contributeRemoteQuestions: PromptObject<string>[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'local_setup_type',
|
||||
message:
|
||||
"We'll be redirecting you to a dedicated Github Codespace. Press enter to continue.",
|
||||
},
|
||||
];
|
||||
|
||||
export const askContributeRemoteQuestions: () => Promise<void> = async () => {
|
||||
await prompts(contributeRemoteQuestions);
|
||||
await open('https://codespaces.new/twentyhq/twenty');
|
||||
};
|
||||
@ -1,43 +0,0 @@
|
||||
import prompts, { PromptObject } from 'prompts';
|
||||
import open from 'open';
|
||||
|
||||
export const demoCloudQuestions: PromptObject<string>[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'continue_cloud',
|
||||
message: 'We will redirect your to the cloud app. Press enter to continue.',
|
||||
},
|
||||
/*
|
||||
In the future we can let user signup from CLI directly before redirecting:
|
||||
{
|
||||
type: 'select',
|
||||
name: 'signup_type',
|
||||
message: 'How do you want to signup?',
|
||||
choices: [
|
||||
{ title: 'Google Sign-in', value: 'google' },
|
||||
{ title: 'Email with magic link', value: 'magic_link' },
|
||||
{ title: 'Email with password', value: 'password' },
|
||||
{ title: 'No-email, demo account with seeds', value: 'seeded_demo' },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: (rep) => (rep == 'google' ? 'text' : null),
|
||||
name: 'google_signup',
|
||||
message:
|
||||
'A new browser window will open to sign you up with Google. Press enter to continue.',
|
||||
},
|
||||
{
|
||||
type: (rep) => {
|
||||
if (rep == 'magic_link' || rep == 'password') {
|
||||
return 'text';
|
||||
}
|
||||
},
|
||||
name: 'email_signup',
|
||||
message: 'Please enter your email',
|
||||
}, */
|
||||
];
|
||||
|
||||
export const askDemoCloudQuestions: () => Promise<void> = async () => {
|
||||
await prompts(demoCloudQuestions);
|
||||
open('https://app.twenty.com');
|
||||
};
|
||||
@ -1,14 +0,0 @@
|
||||
import prompts, { PromptObject } from 'prompts';
|
||||
|
||||
export const demoDockerQuestions: PromptObject<string>[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'not_ready_yet',
|
||||
message: 'Not yeady yet',
|
||||
choices: [{ title: 'XXX', value: 'XXX' }],
|
||||
},
|
||||
];
|
||||
|
||||
export const askDemoDockerQuestions: () => Promise<void> = async () => {
|
||||
await prompts(demoDockerQuestions);
|
||||
};
|
||||
@ -1,27 +0,0 @@
|
||||
import prompts, { PromptObject } from 'prompts';
|
||||
import { askDemoCloudQuestions } from './cloud.js';
|
||||
import { askDemoDockerQuestions } from './docker.js';
|
||||
|
||||
export const demoQuestions: PromptObject<string>[] = [
|
||||
{
|
||||
type: 'select',
|
||||
name: 'demo_type',
|
||||
message: 'How do you want to try the app?',
|
||||
choices: [
|
||||
{ title: 'Cloud demo', value: 'cloud' },
|
||||
{ title: 'Local docker image', value: 'docker', disabled: true },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const askDemoQuestions: () => Promise<void> = async () => {
|
||||
const response = await prompts(demoQuestions);
|
||||
switch (response.demo_type) {
|
||||
case 'cloud':
|
||||
await askDemoCloudQuestions();
|
||||
break;
|
||||
case 'docker':
|
||||
await askDemoDockerQuestions();
|
||||
break;
|
||||
}
|
||||
};
|
||||
@ -1,57 +0,0 @@
|
||||
import gradient from 'gradient-string';
|
||||
import chalk from 'chalk';
|
||||
import { PromptObject } from 'prompts';
|
||||
|
||||
export const showWelcomeScreen = () => {
|
||||
const logo = `
|
||||
|
||||
&&&&&&&&&&&&& &&&&&&&&&&&&&
|
||||
&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&
|
||||
&&&& &&&&& &&&&
|
||||
&&&& &&&&&& &&&&
|
||||
&&&& &&&&&& && &&&&
|
||||
&&&&& &&&& &&&&
|
||||
&&&&&& &&&& &&&&
|
||||
&&&&&& &&&& &&&&
|
||||
&&&&& &&&& &&&&
|
||||
&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&
|
||||
&&&&&&&&&&&&&&&& &&&&&&&&&&&&
|
||||
|
||||
`;
|
||||
|
||||
const items = logo.split('\n').map((row) => gradient.mind(row));
|
||||
|
||||
/* eslint-disable no-console */
|
||||
console.log(chalk.bold(items.join('\n')));
|
||||
console.log(chalk.bold(`Welcome to Twenty!`));
|
||||
console.log(
|
||||
chalk.bold(
|
||||
gradient.mind(`We're building a modern alternative to Salesforce\n`),
|
||||
),
|
||||
);
|
||||
console.log(chalk.bold(`Let's get you started!\n\n`));
|
||||
/* eslint-enable no-console */
|
||||
};
|
||||
|
||||
export const firstQuestion: PromptObject = {
|
||||
type: 'select',
|
||||
name: 'install_type',
|
||||
message: 'What do you want to do?',
|
||||
choices: [
|
||||
{
|
||||
title: 'Contribute to the code',
|
||||
description: 'I want to setup a development environment',
|
||||
value: 'contribute',
|
||||
},
|
||||
{
|
||||
title: 'Quickly try the product',
|
||||
description: 'I want to play with a demo version',
|
||||
value: 'demo',
|
||||
},
|
||||
{
|
||||
title: 'Self-host on a server',
|
||||
description: 'I want to host the app on a distant server',
|
||||
value: 'selfhost',
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -1,16 +0,0 @@
|
||||
import prompts, { PromptObject } from 'prompts';
|
||||
import open from 'open';
|
||||
|
||||
export const selfhostQuestions: PromptObject<string>[] = [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'docker',
|
||||
message:
|
||||
'The options to self-host are documented in the doc. Click enter to open the relevant help page.',
|
||||
},
|
||||
];
|
||||
|
||||
export const askSelfhostQuestions: () => Promise<void> = async () => {
|
||||
await prompts(selfhostQuestions);
|
||||
await open('https://docs.twenty.com/dev-docs/getting-started/self-hosting');
|
||||
};
|
||||
@ -1,14 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "es2020",
|
||||
"strict": true,
|
||||
"outDir": "lib/",
|
||||
"moduleResolution": "nodenext",
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"declaration": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
9
packages/twenty-utils/dangerfile.ts
Normal file
9
packages/twenty-utils/dangerfile.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import {message, danger, warn} from "danger"
|
||||
|
||||
const packageChanged = danger.git.modified_files.includes('package.json');
|
||||
const lockfileChanged = danger.git.modified_files.includes('yarn.lock');
|
||||
if (packageChanged && !lockfileChanged) {
|
||||
const message = 'Changes were made to package.json, but not to yarn.lock';
|
||||
const idea = 'Perhaps you need to run `yarn install`?';
|
||||
warn(`${message} - <i>${idea}</i>`);
|
||||
}
|
||||
12
packages/twenty-utils/package.json
Normal file
12
packages/twenty-utils/package.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "twenty-utils",
|
||||
"scripts": {
|
||||
"release": "node release.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"danger": "^11.3.0"
|
||||
}
|
||||
}
|
||||
1083
packages/twenty-utils/yarn.lock
Normal file
1083
packages/twenty-utils/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user