import * as fs from 'fs-extra'; import { join } from 'path'; import { v4 } from 'uuid'; import { ASSETS_DIR } from 'twenty-shared/application'; const SRC_FOLDER = 'src'; export const copyBaseApplicationProject = async ({ appName, appDisplayName, appDescription, appDirectory, }: { appName: string; appDisplayName: string; appDescription: string; appDirectory: string; }) => { await fs.copy(join(__dirname, './constants/base-application'), appDirectory); await createPackageJson({ appName, appDirectory }); await createGitignore(appDirectory); await createPublicAssetDirectory(appDirectory); await createYarnLock(appDirectory); const sourceFolderPath = join(appDirectory, SRC_FOLDER); await fs.ensureDir(sourceFolderPath); await createDefaultRoleConfig({ displayName: appDisplayName, appDirectory: sourceFolderPath, fileFolder: 'roles', fileName: 'default-role.ts', }); await createDefaultFrontComponent({ appDirectory: sourceFolderPath, fileFolder: 'front-components', fileName: 'hello-world.tsx', }); await createDefaultFunction({ appDirectory: sourceFolderPath, fileFolder: 'logic-functions', fileName: 'hello-world.ts', }); await createApplicationConfig({ displayName: appDisplayName, description: appDescription, appDirectory: sourceFolderPath, fileName: 'application-config.ts', }); }; const createPublicAssetDirectory = async (appDirectory: string) => { await fs.ensureDir(join(appDirectory, ASSETS_DIR)); }; const createYarnLock = async (appDirectory: string) => { const yarnLockContent = `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 `; await fs.writeFile(join(appDirectory, 'yarn.lock'), yarnLockContent); }; const createGitignore = async (appDirectory: string) => { const gitignoreContent = `# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies /node_modules /.pnp .pnp.* .yarn # codegen generated # testing /coverage # dev /dist/ .twenty/* !.twenty/output/ # production /build # misc .DS_Store *.pem # debug npm-debug.log* yarn-debug.log* yarn-error.log* .pnpm-debug.log* # env files (can opt-in for committing if needed) .env* # typescript *.tsbuildinfo `; await fs.writeFile(join(appDirectory, '.gitignore'), gitignoreContent); }; const createDefaultRoleConfig = async ({ displayName, appDirectory, fileFolder, fileName, }: { displayName: string; appDirectory: string; fileFolder?: string; fileName: string; }) => { const universalIdentifier = v4(); const content = `import { defineRole } from 'twenty-sdk'; export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = '${universalIdentifier}'; export default defineRole({ universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER, label: '${displayName} default function role', description: '${displayName} default function role', canReadAllObjectRecords: true, canUpdateAllObjectRecords: true, canSoftDeleteAllObjectRecords: true, canDestroyAllObjectRecords: false, }); `; await fs.ensureDir(join(appDirectory, fileFolder ?? '')); await fs.writeFile(join(appDirectory, fileFolder ?? '', fileName), content); }; const createDefaultFrontComponent = async ({ appDirectory, fileFolder, fileName, }: { appDirectory: string; fileFolder?: string; fileName: string; }) => { const universalIdentifier = v4(); const content = `import { defineFrontComponent } from 'twenty-sdk'; export const HelloWorld = () => { return (
This is your first front component.