Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Added setup script for the starter kit users. #22

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .modules.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
lens
ai
poh
sismo
29 changes: 20 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@ All essential components to start building an amazing dapp with interoperable wo

## Start building in 60 seconds

- Fork the code
- Clone your new repository
- Clone this repository

- Copy .env.example file into a new .env file
- `cp .env.example .env`
`cp .env.example .env`

- If you are using nvm, run:
- `nvm use`
`nvm use`
- Else, use the recommended node version: `18^`

-Install the dependencies
- `npm install`
- Install the dependencies
`npm install`

-Run local server for development
- `npm run dev`
- Run the setup script to choose the modules which you want to use in your project
`npm run setup`

- Run local server for development
`npm run dev`

## 🛠️ TalentLayer

Expand All @@ -43,4 +45,13 @@ XMTP is an open protocol and dev toolkit for messaging applications. You can use

**Documentation:** [Read here.](https://xmtp.org/docs/dev-concepts/start-building)

**Example DAPP Tutorial:** [Read here.](https://xmtp.org/docs/client-sdk/javascript/tutorials/build-an-xmtp-hello-world-app)
**Example DAPP Tutorial:** [Read here.](https://xmtp.org/docs/client-sdk/javascript/tutorials/build-an-xmtp-hello-world-app)

## Contribution Guide (for the setup script templating)

Whenever you need to add more optional modules in the starter kit, you need to do the following steps:
- Add the module's unique name in the .modules.template file
- The module folder should contain a file `.module-${module_name}`
- The files which use this module should have the module markers (no need if the file is present in a folder which has `.module-${module_name}` file):
- if the file is useless if the module is not selected then on the top of the file add a comment `// MODULE_FILE:${module_name}`
- else if the file has some sections which are useless if module not selected, then add one comment just above the section `// MODULE_SECTION_START:${module_name}` (in case of jsx or tsx code, `{/* MODULE_SECTION_START:${module_name} */}`), then add one comment just below the section `// MODULE_SECTION_END` (in case of jsx or tsx code, `{/* MODULE_SECTION_END */}`)
141 changes: 141 additions & 0 deletions bin/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import fs from 'fs';
import path from 'path';

const startPattern1 = /^{\/\*[\*]{0,1} MODULE_SECTION_START:(([a-zA-Z]+),)*([a-zA-Z]+)+ \*\/}$/;
const startPattern2 = /^\/\/ MODULE_SECTION_START:(([a-zA-Z]+),)*([a-zA-Z]+)+$/;
const selectionPattern1 = /^{\/\*[\*]{0,1} MODULE_SECTION_START:([a-zA-Z,]+)+ \*\/}$/;
const selectionPattern2 = /^\/\/ MODULE_SECTION_START:([a-zA-Z,]+)+$/;
const endPattern1 = /^{\/\*[\*]{0,1} MODULE_SECTION_END \*\/}$/;
const endPattern2 = /^\/\/ MODULE_SECTION_END$/;

function deleteIfUnselectedModuleFile(filePath, supportedModules, selectedModules) {
const content = fs.readFileSync(filePath);
const codeLines = content.toString('utf-8').trim().split('\n');

if (codeLines[0].trim().startsWith('// MODULE_FILE:')) {
const requiredModules = codeLines[0]
.trim()
.slice(15)
.split(',')
.filter(moduleName => supportedModules.includes(moduleName));

if (requiredModules.length === 0) return;
if (!requiredModules.some(moduleName => selectedModules.includes(moduleName))) {
// delete the file
fs.rmSync(filePath);
}
return true;
}
return false;
}

function deleteUnselectedModuleCode(filePath, supportedModules, selectedModules) {
// read the file for the markers
const content = fs.readFileSync(filePath);
const codeLines = content.toString('utf-8').trim().split('\n');
const usefulLines = [];
let state = 0;
let pattern = 0;
for (let i = 0; i < codeLines.length; i++) {
const line = codeLines[i].trim();

let patternLine = false;
(() => {
if (state == 0) {
let requiredModules = [];
if (startPattern1.test(line)) {
pattern = 1;
const groups = line.match(selectionPattern1);
requiredModules = groups[1]
.split(',')
.filter(moduleName => supportedModules.includes(moduleName));
} else if (startPattern2.test(line)) {
pattern = 2;
const groups = line.match(selectionPattern2);
requiredModules = groups[1]
.split(',')
.filter(moduleName => supportedModules.includes(moduleName));
} else return;
if (requiredModules.length === 0) return;

patternLine = true;

state = requiredModules.some(moduleName => selectedModules.includes(moduleName)) ? 1 : 2;
} else {
if (
(pattern === 1 && endPattern1.test(line)) ||
(pattern === 2 && endPattern2.test(line))
) {
pattern = 0;
state = 0;
patternLine = true;
}
}
})();

if (state != 2 && !patternLine) {
usefulLines.push(i);
}
}
const newFileContent = usefulLines.map(i => codeLines[i]).join('\n');
if (usefulLines.length !== codeLines.length) fs.writeFileSync(filePath, newFileContent);
}

function handleFile(filePath, supportedModules, selectedModules) {
if (!['ts', 'js', 'jsx', 'tsx'].includes(filePath.split('.')[filePath.split('.').length - 1]))
return;

if (deleteIfUnselectedModuleFile(filePath, supportedModules, selectedModules)) return;

deleteUnselectedModuleCode(filePath, supportedModules, selectedModules);
}

function handleDirectory(dirPath, supportedModules, selectedModules, ignoredFiles) {
const pattern = /^.module-[a-zA-Z0-9_]+$/;
const requiredModules = fs
.readdirSync(dirPath)
.filter(fileName => pattern.test(fileName))
.map(fileName => fileName.slice(8))
.filter(moduleName => supportedModules.includes(moduleName));
if (requiredModules.length === 0) {
removeUnselectedModules(dirPath, supportedModules, selectedModules, ignoredFiles);
return;
}
if (!requiredModules.some(moduleName => selectedModules.includes(moduleName))) {
// delete the directory
fs.rmSync(dirPath, { recursive: true });
} else {
// delete the .module files
for (const requiredModule of requiredModules) {
fs.rmSync(path.join(dirPath, `.module-${requiredModule}`));
}
}
}

export function removeUnselectedModules(
basePath,
supportedModules,
selectedModules,
ignoredFiles = [],
) {
const dirContents = fs.readdirSync(basePath);
if (dirContents.includes('.gitignore')) {
for (const objName of fs
.readFileSync(path.join(basePath, '.gitignore'))
.toString('utf-8')
.trim()
.split('\n')
.filter(name => Boolean(name))) {
ignoredFiles.push(objName);
}
}
for (const obj of dirContents) {
if (ignoredFiles.includes(obj)) continue;
const objPath = path.join(basePath, obj);
if (fs.statSync(objPath).isDirectory()) {
handleDirectory(objPath, supportedModules, selectedModules, ignoredFiles);
} else {
handleFile(objPath, supportedModules, selectedModules);
}
}
}
37 changes: 37 additions & 0 deletions bin/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env node

import fs from 'fs';
import { removeUnselectedModules } from './helpers.js';
import inquirer from 'inquirer';
import { execSync } from 'child_process';

// copy the modules file
if (!fs.existsSync(`./.modules.template`)) process.exit(0);

const modules = fs
.readFileSync(`./.modules.template`)
.toString('utf-8')
.trim()
.split('\n')
.map(module => module.trim());

// run some cli function to get the module choises
inquirer
.prompt([
{
type: 'checkbox',
message: 'Select modules',
name: 'selectedModules',
choices: modules.map(moduleName => ({ name: moduleName })),
},
])
.then(({ selectedModules }) => {
removeUnselectedModules(`.`, modules, selectedModules);

fs.rmSync(`./.modules.template`);
execSync('npm run format');
execSync('rm -r .git');
execSync('git init');
execSync('git add .');
execSync('git commit -m "initial commit"');
});
Loading