UNPKG

@iexec/iapp

Version:

A CLI to guide you through the process of building an iExec iApp

181 lines (170 loc) 4.78 kB
import fs from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { CONFIG_FILE, TEST_INPUT_DIR, TEST_OUTPUT_DIR, CACHE_DIR, PROTECTED_DATA_MOCK_DIR, TEMPLATES, TemplateName, } from '../config/config.js'; import { debug } from './debug.js'; import { copy } from './fs.utils.js'; export async function initIAppWorkspace({ projectName, template = 'JavaScript', useArgs = false, useProtectedData = false, useInputFile = false, useRequesterSecret = false, useAppSecret = false, }: { projectName: string; template: TemplateName; useArgs?: boolean; useProtectedData?: boolean; useInputFile?: boolean; useRequesterSecret?: boolean; useAppSecret?: boolean; }) { try { // Copy template await copyChosenTemplateFiles({ template, srcFiles: TEMPLATES[template]?.sourceFiles, useArgs, useProtectedData, useInputFile, useRequesterSecret, useAppSecret, }); // Create other files await createConfigurationFiles({ projectName, template, appSecret: useAppSecret ? undefined : null, // save `appSecret: null` to disable prompt when `useAppSecret: false` }); await createProjectDirectories(); } catch (err) { debug('Error during project initialization:', err); throw err; } } async function createProjectDirectories() { await Promise.all([ fs.mkdir(TEST_INPUT_DIR, { recursive: true }), fs.mkdir(TEST_OUTPUT_DIR, { recursive: true }), fs.mkdir(CACHE_DIR, { recursive: true }), ]); } async function createConfigurationFiles({ projectName, appSecret, template, }: { projectName: string; appSecret?: string | null; template: string; }) { // Create a simple iApp configuration file const configContent = { projectName, template, appSecret, }; await fs.writeFile( CONFIG_FILE, JSON.stringify(configContent, null, 2), 'utf8' ); } async function copyChosenTemplateFiles({ template, srcFiles, useArgs, useProtectedData, useInputFile, useRequesterSecret, useAppSecret, }: { template: string; srcFiles: string[]; useArgs: boolean; useProtectedData: boolean; useInputFile: boolean; useRequesterSecret: boolean; useAppSecret: boolean; }) { const templatesBaseDir = path.resolve( fileURLToPath(import.meta.url), '../../..', 'templates' ); const write = async (file: string, content?: string) => { const targetPath = path.join(process.cwd(), file); if (content) { await fs.writeFile(targetPath, content); } else { await copy(path.join(templateDir, file), targetPath); } }; // copy selected template const templateDir = path.resolve(templatesBaseDir, template); const files = await fs.readdir(templateDir); await Promise.all(files.map((file) => write(file))); // rename _.gitignore (npm does not allow publishing files named .gitignore in a package) await fs.rename('_.gitignore', '.gitignore'); for (const srcFile of srcFiles) { // transform template: remove unwanted feature code inside " // <<feature>> ... // <</feature>>" tags const code = (await fs.readFile(srcFile)).toString('utf8'); let modifiedCode = code; if (!useArgs) { modifiedCode = modifiedCode.replaceAll( / *(\/\/|#) <<args>>\n((.*)\n)*? *(\/\/|#) <<\/args>>(\n)?/g, '' ); } if (!useProtectedData) { modifiedCode = modifiedCode.replaceAll( / *(\/\/|#) <<protectedData>>\n((.*)\n)*? *(\/\/|#) <<\/protectedData>>(\n)?/g, '' ); } if (!useInputFile) { modifiedCode = modifiedCode.replaceAll( / *(\/\/|#) <<inputFile>>\n((.*)\n)*? *(\/\/|#) <<\/inputFile>>(\n)?/g, '' ); } if (!useRequesterSecret) { modifiedCode = modifiedCode.replaceAll( / *(\/\/|#) <<requesterSecret>>\n((.*)\n)*? *(\/\/|#) <<\/requesterSecret>>(\n)?/g, '' ); } if (!useAppSecret) { modifiedCode = modifiedCode.replaceAll( / *(\/\/|#) <<appSecret>>\n((.*)\n)*? *(\/\/|#) <<\/appSecret>>(\n)?/g, '' ); } // clean remaining <<feature>> tags modifiedCode = modifiedCode.replaceAll(/ *(\/\/|#) <<(\/)?.*>>(\n)?/g, ''); // delete finally empty file if (modifiedCode === '' || modifiedCode === '\n') { await fs.rm(srcFile); } else { // or update content await fs.writeFile(srcFile, modifiedCode); } } // copy common const commonPath = path.resolve(templatesBaseDir, 'common'); await copy(commonPath, path.join(process.cwd())); if (useProtectedData) { const mockPath = path.resolve(templatesBaseDir, 'mock', 'protectedData'); await copy(mockPath, PROTECTED_DATA_MOCK_DIR); } }