Skip to main content
Glama

mcp-google-sheets

create-piece.ts6.76 kB
import chalk from 'chalk'; import { Command } from 'commander'; import { readdir, unlink, writeFile } from 'fs/promises'; import inquirer from 'inquirer'; import assert from 'node:assert'; import { exec } from '../utils/exec'; import { readPackageEslint, readProjectJson, writePackageEslint, writeProjectJson, } from '../utils/files'; import { findPiece } from '../utils/piece-utils'; const validatePieceName = async (pieceName: string) => { console.log(chalk.yellow('Validating piece name....')); const pieceNamePattern = /^(?![._])[a-z0-9-]{1,214}$/; if (!pieceNamePattern.test(pieceName)) { console.log( chalk.red( `🚨 Invalid piece name: ${pieceName}. Piece names can only contain lowercase letters, numbers, and hyphens.` ) ); process.exit(1); } }; const validatePackageName = async (packageName: string) => { console.log(chalk.yellow('Validating package name....')); const packageNamePattern = /^(?:@[a-zA-Z0-9-]+\/)?[a-zA-Z0-9-]+$/; if (!packageNamePattern.test(packageName)) { console.log( chalk.red( `🚨 Invalid package name: ${packageName}. Package names can only contain lowercase letters, numbers, and hyphens.` ) ); process.exit(1); } }; const checkIfPieceExists = async (pieceName: string) => { const pieceFolder = await findPiece(pieceName); if (pieceFolder) { console.log(chalk.red(`🚨 Piece already exists at ${pieceFolder}`)); process.exit(1); } }; const nxGenerateNodeLibrary = async ( pieceName: string, packageName: string, pieceType: string ) => { const nxGenerateCommand = [ `npx nx generate @nx/node:library`, `--directory=packages/pieces/${pieceType}/${pieceName}`, `--name=pieces-${pieceName}`, `--importPath=${packageName}`, '--publishable', '--buildable', '--projectNameAndRootFormat=as-provided', '--strict', '--unitTestRunner=none', ].join(' '); console.log(chalk.blue(`🛠️ Executing nx command: ${nxGenerateCommand}`)); await exec(nxGenerateCommand); }; const removeUnusedFiles = async (pieceName: string, pieceType: string) => { const path = `packages/pieces/${pieceType}/${pieceName}/src/lib/`; const files = await readdir(path); for (const file of files) { await unlink(path + file); } }; function capitalizeFirstLetter(str: string): string { return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); } const generateIndexTsFile = async (pieceName: string, pieceType: string) => { const pieceNameCamelCase = pieceName .split('-') .map((s, i) => { if (i === 0) { return s; } return s[0].toUpperCase() + s.substring(1); }) .join(''); const indexTemplate = ` import { createPiece, PieceAuth } from "@activepieces/pieces-framework"; export const ${pieceNameCamelCase} = createPiece({ displayName: "${capitalizeFirstLetter(pieceName)}", auth: PieceAuth.None(), minimumSupportedRelease: '0.36.1', logoUrl: "https://cdn.activepieces.com/pieces/${pieceName}.png", authors: [], actions: [], triggers: [], }); `; await writeFile( `packages/pieces/${pieceType}/${pieceName}/src/index.ts`, indexTemplate ); }; const updateProjectJsonConfig = async ( pieceName: string, pieceType: string ) => { const projectJson = await readProjectJson( `packages/pieces/${pieceType}/${pieceName}` ); const i18nAsset = { input: `packages/pieces/${pieceType}/${pieceName}/src/i18n`, output: './src/i18n', glob: '**/!(i18n.json)' } assert( projectJson.targets?.build?.options, '[updateProjectJsonConfig] targets.build.options is required' ); projectJson.targets.build.options.buildableProjectDepsInPackageJsonType = 'dependencies'; projectJson.targets.build.options.updateBuildableProjectDepsInPackageJson = true; if(projectJson.targets.build.options.assets){ projectJson.targets.build.options.assets.push(i18nAsset); } else{ projectJson.targets.build.options.assets = [i18nAsset]; } const lintFilePatterns = projectJson.targets.lint?.options?.lintFilePatterns; if (lintFilePatterns) { const patternIndex = lintFilePatterns.findIndex((item) => item.endsWith('package.json') ); if (patternIndex !== -1) lintFilePatterns?.splice(patternIndex, 1); } else { projectJson.targets.lint = { executor: '@nx/eslint:lint', outputs: ['{options.outputFile}'], }; } await writeProjectJson( `packages/pieces/${pieceType}/${pieceName}`, projectJson ); }; const addEslintFile = async (pieceName: string, pieceType: string) => { const eslintFile ={ "extends": ["../../../../.eslintrc.base.json"], "ignorePatterns": ["!**/*"], "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": {} }, { "files": ["*.ts", "*.tsx"], "rules": {} }, { "files": ["*.js", "*.jsx"], "rules": {} } ] } await writePackageEslint( `packages/pieces/${pieceType}/${pieceName}`, eslintFile ); }; const setupGeneratedLibrary = async (pieceName: string, pieceType: string) => { await removeUnusedFiles(pieceName, pieceType); await generateIndexTsFile(pieceName, pieceType); await updateProjectJsonConfig(pieceName, pieceType); await addEslintFile(pieceName, pieceType); }; export const createPiece = async ( pieceName: string, packageName: string, pieceType: string ) => { await validatePieceName(pieceName); await validatePackageName(packageName); await checkIfPieceExists(pieceName); await nxGenerateNodeLibrary(pieceName, packageName, pieceType); await setupGeneratedLibrary(pieceName, pieceType); console.log(chalk.green('✨ Done!')); console.log( chalk.yellow( `The piece has been generated at: packages/pieces/${pieceType}/${pieceName}` ) ); }; export const createPieceCommand = new Command('create') .description('Create a new piece') .action(async () => { const questions = [ { type: 'input', name: 'pieceName', message: 'Enter the piece name:', }, { type: 'input', name: 'packageName', message: 'Enter the package name:', default: (answers: any) => `@activepieces/piece-${answers.pieceName}`, when: (answers: any) => answers.pieceName !== undefined, }, { type: 'list', name: 'pieceType', message: 'Select the piece type:', choices: ['community', 'custom'], default: 'community', }, ]; const answers = await inquirer.prompt(questions); createPiece(answers.pieceName, answers.packageName, answers.pieceType); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server