From 501bbaeabd768d32c3128a571708abd92c8cd194 Mon Sep 17 00:00:00 2001 From: weboko Date: Mon, 5 Dec 2022 20:33:33 +0100 Subject: [PATCH 01/14] init create-waku-app --- packages/create-waku-app/package.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 packages/create-waku-app/package.json diff --git a/packages/create-waku-app/package.json b/packages/create-waku-app/package.json new file mode 100644 index 0000000..1ba317a --- /dev/null +++ b/packages/create-waku-app/package.json @@ -0,0 +1,22 @@ +{ + "name": "create-waku-app", + "version": "0.1.0", + "description": "Helper package to bootstrap Waku app ", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "waku", + "decentralised", + "communication", + "web3", + "ethereum", + "dapps" + ], + "license": "MIT OR Apache-2.0", + "dependencies": { + "commander": "^9.4.1" + } + } + \ No newline at end of file From 32ea01a1350084fc2636b51085fe92ca2a63722a Mon Sep 17 00:00:00 2001 From: weboko Date: Mon, 5 Dec 2022 20:34:15 +0100 Subject: [PATCH 02/14] add index.js --- packages/create-waku-app/index.js | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 packages/create-waku-app/index.js diff --git a/packages/create-waku-app/index.js b/packages/create-waku-app/index.js new file mode 100644 index 0000000..28bb83d --- /dev/null +++ b/packages/create-waku-app/index.js @@ -0,0 +1,4 @@ +#!/usr/bin/env node +const { createApp } = require("./createWakuApp"); + +createApp(); From af0c0cf1b0ebac3769492c724d3a5a2836bb7d78 Mon Sep 17 00:00:00 2001 From: weboko Date: Mon, 5 Dec 2022 20:34:44 +0100 Subject: [PATCH 03/14] user commander to handle command --- packages/create-waku-app/createWakuApp.js | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 packages/create-waku-app/createWakuApp.js diff --git a/packages/create-waku-app/createWakuApp.js b/packages/create-waku-app/createWakuApp.js new file mode 100644 index 0000000..4285fb2 --- /dev/null +++ b/packages/create-waku-app/createWakuApp.js @@ -0,0 +1,28 @@ +const { Command } = require('commander'); + +const packageJson = require('./package.json'); + +let appName; + +const createApp = () => { + const program = new Command() + .name(packageJson.name) + .description(packageJson.description) + .version(packageJson.version) + .arguments("", "Project directory to initialize Waku app") + .action(name => { + appName = name; + }) + .option( + "-t, --template ", + "specify a template for the created project" + ) + .allowUnknownOption() + .parse(); + + const options = program.opts(); + + console.log(`Initializing ${appName} from template ${options.template || "default"}`); +}; + +module.exports = { createApp }; \ No newline at end of file From 2d857b43cdcf580bdb836711ca860c4ab545d8c3 Mon Sep 17 00:00:00 2001 From: weboko Date: Mon, 5 Dec 2022 20:35:05 +0100 Subject: [PATCH 04/14] ignore package-lock.json --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 88b3bfc..acb715d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ dist node_modules yarn.lock +package-lock.json From e7f68732cb0a15139a2d3c942453cc606773c861 Mon Sep 17 00:00:00 2001 From: weboko Date: Tue, 6 Dec 2022 21:02:56 +0100 Subject: [PATCH 05/14] add .gitignore and empty README --- packages/create-waku-app/.gitignore | 2 ++ packages/create-waku-app/README.md | 0 2 files changed, 2 insertions(+) create mode 100644 packages/create-waku-app/.gitignore create mode 100644 packages/create-waku-app/README.md diff --git a/packages/create-waku-app/.gitignore b/packages/create-waku-app/.gitignore new file mode 100644 index 0000000..577e9e6 --- /dev/null +++ b/packages/create-waku-app/.gitignore @@ -0,0 +1,2 @@ +examples +package-lock.json \ No newline at end of file diff --git a/packages/create-waku-app/README.md b/packages/create-waku-app/README.md new file mode 100644 index 0000000..e69de29 From 874c2477a8d5d5a1b7d83f5587438e6c3aaf4b5c Mon Sep 17 00:00:00 2001 From: weboko Date: Tue, 6 Dec 2022 21:03:34 +0100 Subject: [PATCH 06/14] create build scrupt, make adjustments to use examples from package json --- packages/create-waku-app/build.js | 42 +++++++++++++ packages/create-waku-app/createApp.js | 76 +++++++++++++++++++++++ packages/create-waku-app/createWakuApp.js | 28 --------- packages/create-waku-app/index.js | 19 +++++- packages/create-waku-app/package.json | 59 ++++++++++++++---- 5 files changed, 181 insertions(+), 43 deletions(-) create mode 100644 packages/create-waku-app/build.js create mode 100644 packages/create-waku-app/createApp.js delete mode 100644 packages/create-waku-app/createWakuApp.js diff --git a/packages/create-waku-app/build.js b/packages/create-waku-app/build.js new file mode 100644 index 0000000..32327f1 --- /dev/null +++ b/packages/create-waku-app/build.js @@ -0,0 +1,42 @@ +#!/usr/bin/env node +const path = require("path"); +const fs = require("fs-extra"); + +const packageJson = require("./package.json"); +const examplesFolder = path.resolve("./examples"); + +async function run() { + fs.ensureDirSync(examplesFolder); + + const supportedExamples = Object.entries(packageJson.wakuExamples); + + console.log("Started copying supported Waku examples."); + + const copyPromises = supportedExamples.map(([name, relativePath]) => { + const resolvedPath = path.resolve(__dirname, relativePath); + const destinationPath = path.resolve(examplesFolder, name); + + return fs.copy(resolvedPath, destinationPath, { filter: nodeModulesFiler }).catch((error) => { + console.error(`Failed to copy example ${name} to ${destinationPath} with ${error.message}`); + throw Error(error.message); + }); + }); + + await Promise.all(copyPromises) + .then(() => { + console.log("Finished copying examples."); + }) + .catch((error) => { + console.error("Failed to copy examples due to " + error.message); + }); +} + +function nodeModulesFiler(src) { + if (src.includes("node_modules")) { + return false; + } + + return true; +} + +run(); diff --git a/packages/create-waku-app/createApp.js b/packages/create-waku-app/createApp.js new file mode 100644 index 0000000..0b4444f --- /dev/null +++ b/packages/create-waku-app/createApp.js @@ -0,0 +1,76 @@ +const fs = require("fs-extra"); +const path = require("path"); +const { Command } = require('commander'); +const validateProjectName = require('validate-npm-package-name'); + +const supportedExamplesDir = path.resolve("./examples"); + +const init = (name, description, version, supportedExamples) => { + let appName; + const program = new Command() + .name(name) + .description(description) + .version(version, "-v, --version", "output the version number") + .arguments("", "Project directory to initialize Waku app") + .action(_appName => { + appName = _appName; + }) + .option( + "-t, --template ", + "specify a template for the created project" + ) + .allowUnknownOption() + .parse(); + + const options = program.opts(); + const template = options.template || "web-chat"; + + if (!supportedExamples[template]) { + const supportedExamplesMessage = Object.keys(supportedExamples).reduce((acc, v) => { + acc += `\t${v}\n`; + return acc; + }, ""); + + console.error(`Unknown template: ${template}`); + console.error(`We support only following templates:\n${supportedExamplesMessage}`) + process.exit(1); + } + + createApp(appName, template); +}; + +function createApp(name, template) { + const appRoot = path.resolve(name); + const appName = path.basename(appRoot); + + const templateDir = path.resolve(supportedExamplesDir, template); + + terminateIfAppExists(appName); + terminateIfProjectNameInvalid(appName); + + console.log(`Initializing ${appName} from ${template} template.`); + + fs.copySync(templateDir, appRoot); + // initNpmOrYarn(appRoot); +} + +function terminateIfProjectNameInvalid(name) { + const validationResult = validateProjectName(name); + + if (!validationResult.validForNewPackages) { + console.error(`Cannot create a project named ${name} because of npm naming restrictions:\n`); + [...(validationResult.errors || []), ...(validationResult.warnings || [])] + .forEach(error => console.error(` * ${error}`)); + console.error("\nPlease choose a different project name."); + process.exit(1); + } +} + +function terminateIfAppExists(appRoot) { + if (fs.existsSync(appRoot)) { + console.error(`Cannot create a project because it already exists by the name: ${appRoot}`); + process.exit(1); + } +} + +module.exports = { init }; \ No newline at end of file diff --git a/packages/create-waku-app/createWakuApp.js b/packages/create-waku-app/createWakuApp.js deleted file mode 100644 index 4285fb2..0000000 --- a/packages/create-waku-app/createWakuApp.js +++ /dev/null @@ -1,28 +0,0 @@ -const { Command } = require('commander'); - -const packageJson = require('./package.json'); - -let appName; - -const createApp = () => { - const program = new Command() - .name(packageJson.name) - .description(packageJson.description) - .version(packageJson.version) - .arguments("", "Project directory to initialize Waku app") - .action(name => { - appName = name; - }) - .option( - "-t, --template ", - "specify a template for the created project" - ) - .allowUnknownOption() - .parse(); - - const options = program.opts(); - - console.log(`Initializing ${appName} from template ${options.template || "default"}`); -}; - -module.exports = { createApp }; \ No newline at end of file diff --git a/packages/create-waku-app/index.js b/packages/create-waku-app/index.js index 28bb83d..c8bd301 100644 --- a/packages/create-waku-app/index.js +++ b/packages/create-waku-app/index.js @@ -1,4 +1,19 @@ #!/usr/bin/env node -const { createApp } = require("./createWakuApp"); +const packageJson = require("./package.json"); +const semver = require("semver"); -createApp(); +const currentNodeVersion = process.versions.node; +const supportedNodeVersion = packageJson.engines.node; + +if (!semver.satisfies(currentNodeVersion, supportedNodeVersion)) { + console.error( + `You are running Node ${currentNodeVersion}.\n` + + `@waku/create-app works only with ${packageJson.engines.node}.\n` + + `Please update your version of Node.` + ); + process.exit(1); +} + +const { init } = require("./createApp"); + +init(packageJson.name, packageJson.description, packageJson.version, packageJson.wakuExamples); diff --git a/packages/create-waku-app/package.json b/packages/create-waku-app/package.json index 1ba317a..90d8738 100644 --- a/packages/create-waku-app/package.json +++ b/packages/create-waku-app/package.json @@ -1,22 +1,55 @@ { - "name": "create-waku-app", - "version": "0.1.0", + "name": "create-dementor-app", + "version": "0.1.13", "description": "Helper package to bootstrap Waku app ", + "repository": { + "type": "git", + "url": "https://github.com/waku-org/js-waku-examples.git", + "directory": "packages/create-app" + }, + "engines": { + "node": ">=16" + }, + "bugs": { + "url": "https://github.com/waku-org/js-waku-examples/issues" + }, + "files": [ + "index.js", + "createApp.js", + "examples" + ], "main": "index.js", + "bin": { + "create-waku-app": "./index.js" + }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "build": "node ./build.js", + "prepublishOnly": "npm run build" }, "keywords": [ - "waku", - "decentralised", - "communication", - "web3", - "ethereum", - "dapps" + "waku", + "decentralised", + "communication", + "web3", + "ethereum", + "dapps" ], - "license": "MIT OR Apache-2.0", + "license": "MIT", + "wakuExamples": { + "eth-pm": "../../eth-pm", + "light-js": "../../light-js", + "relay-angular-chat": "../../relay-angular-chat", + "relay-js": "../../relay-js", + "relay-reactjs-chat": "../../relay-reactjs-chat", + "rln-js": "../../rln-js", + "store-js": "../../store-js", + "store-reactjs-chat": "../../store-reactjs-chat", + "web-chat": "../../web-chat" + }, "dependencies": { - "commander": "^9.4.1" + "commander": "^9.4.1", + "fs-extra": "^11.1.0", + "semver": "^7.3.8", + "validate-npm-package-name": "^5.0.0" } - } - \ No newline at end of file +} From c1f476dd802b2c5f2bb4b30b1172066c5735e954 Mon Sep 17 00:00:00 2001 From: weboko Date: Tue, 6 Dec 2022 21:04:29 +0100 Subject: [PATCH 07/14] change package name, reset version --- packages/create-waku-app/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/create-waku-app/package.json b/packages/create-waku-app/package.json index 90d8738..0e00cc1 100644 --- a/packages/create-waku-app/package.json +++ b/packages/create-waku-app/package.json @@ -1,6 +1,6 @@ { - "name": "create-dementor-app", - "version": "0.1.13", + "name": "@waku/create-app", + "version": "0.1.0", "description": "Helper package to bootstrap Waku app ", "repository": { "type": "git", From 4126f416ff597e61328c75da29ff5a88b5a1d577 Mon Sep 17 00:00:00 2001 From: weboko Date: Tue, 6 Dec 2022 22:24:44 +0100 Subject: [PATCH 08/14] add npm and git init functions --- packages/create-waku-app/createApp.js | 45 ++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/packages/create-waku-app/createApp.js b/packages/create-waku-app/createApp.js index 0b4444f..9f72b27 100644 --- a/packages/create-waku-app/createApp.js +++ b/packages/create-waku-app/createApp.js @@ -1,7 +1,9 @@ -const fs = require("fs-extra"); const path = require("path"); -const { Command } = require('commander'); -const validateProjectName = require('validate-npm-package-name'); +const fs = require("fs-extra"); +const execSync = require("child_process").execSync; + +const { Command } = require("commander"); +const validateProjectName = require("validate-npm-package-name"); const supportedExamplesDir = path.resolve("./examples"); @@ -51,7 +53,42 @@ function createApp(name, template) { console.log(`Initializing ${appName} from ${template} template.`); fs.copySync(templateDir, appRoot); - // initNpmOrYarn(appRoot); + + moveToDir(appRoot); + + runNpmInApp(appRoot); + runGitInit(appRoot); +} + +function runNpmInApp(root) { + try { + execSync(`npm install --prefix ${root}`, { stdio: "ignore" }); + console.log("Successfully installed npm dependencies."); + } catch (e) { + console.warn("Failed to install npm dependencies", e); + } +} + +function runGitInit(root) { + if (isInGitRepository()) { + return; + } + + try { + execSync(`git init ${root}`, { stdio: "ignore" }); + console.log("Successfully initialized git repo."); + } catch (e) { + console.warn("Git repo not initialized", e); + } +} + +function isInGitRepository() { + try { + execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" }); + return true; + } catch (e) { + return false; + } } function terminateIfProjectNameInvalid(name) { From f08d49542bb1d02eec7a22d0173c8db02769a2d3 Mon Sep 17 00:00:00 2001 From: weboko Date: Tue, 6 Dec 2022 22:34:24 +0100 Subject: [PATCH 09/14] add log messages, remove unused function --- packages/create-waku-app/createApp.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/create-waku-app/createApp.js b/packages/create-waku-app/createApp.js index 9f72b27..108d364 100644 --- a/packages/create-waku-app/createApp.js +++ b/packages/create-waku-app/createApp.js @@ -5,7 +5,7 @@ const execSync = require("child_process").execSync; const { Command } = require("commander"); const validateProjectName = require("validate-npm-package-name"); -const supportedExamplesDir = path.resolve("./examples"); +const supportedExamplesDir = path.resolve(__dirname, "./examples"); const init = (name, description, version, supportedExamples) => { let appName; @@ -52,15 +52,15 @@ function createApp(name, template) { console.log(`Initializing ${appName} from ${template} template.`); + fs.ensureDirSync(appName); fs.copySync(templateDir, appRoot); - moveToDir(appRoot); - runNpmInApp(appRoot); runGitInit(appRoot); } function runNpmInApp(root) { + console.log("Installing npm packages."); try { execSync(`npm install --prefix ${root}`, { stdio: "ignore" }); console.log("Successfully installed npm dependencies."); @@ -74,6 +74,7 @@ function runGitInit(root) { return; } + console.log("Initiating git repository."); try { execSync(`git init ${root}`, { stdio: "ignore" }); console.log("Successfully initialized git repo."); From 922c8d0d1abdf93d48510d9c86f02d51f93b70f7 Mon Sep 17 00:00:00 2001 From: weboko Date: Tue, 6 Dec 2022 22:46:16 +0100 Subject: [PATCH 10/14] add const --- packages/create-waku-app/createApp.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/create-waku-app/createApp.js b/packages/create-waku-app/createApp.js index 108d364..add5ca6 100644 --- a/packages/create-waku-app/createApp.js +++ b/packages/create-waku-app/createApp.js @@ -5,6 +5,7 @@ const execSync = require("child_process").execSync; const { Command } = require("commander"); const validateProjectName = require("validate-npm-package-name"); +const DEFAULT_TEMPLATE = "web-chat"; const supportedExamplesDir = path.resolve(__dirname, "./examples"); const init = (name, description, version, supportedExamples) => { @@ -25,7 +26,7 @@ const init = (name, description, version, supportedExamples) => { .parse(); const options = program.opts(); - const template = options.template || "web-chat"; + const template = options.template || DEFAULT_TEMPLATE; if (!supportedExamples[template]) { const supportedExamplesMessage = Object.keys(supportedExamples).reduce((acc, v) => { From 75d7b16cfb1ff28106508e5ee21deba9fc93a657 Mon Sep 17 00:00:00 2001 From: weboko Date: Tue, 6 Dec 2022 23:18:55 +0100 Subject: [PATCH 11/14] add basic README --- packages/create-waku-app/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/create-waku-app/README.md b/packages/create-waku-app/README.md index e69de29..6427100 100644 --- a/packages/create-waku-app/README.md +++ b/packages/create-waku-app/README.md @@ -0,0 +1,12 @@ +## @waku/create-app + +This package is here to help you bootstrap your next Waku dapp. + +Usage: +- `yarn create @waku/app [options] ` +- `npx @waku/create-app [options] ` + +For options you can specify template from which to initialize your app. Template correlates directly to the name of example you can see in this repository. + +#### How to add support for new example: +Extend `wakuExamples` property defined in `package.json` in this package with the name of the example and relative path to it where folder of the example should be the same as it's name. \ No newline at end of file From efd431914fc03a546fe8734a16f1b300c409585d Mon Sep 17 00:00:00 2001 From: Sasha <118575614+weboko@users.noreply.github.com> Date: Wed, 7 Dec 2022 09:31:52 +0100 Subject: [PATCH 12/14] move to original license Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> --- packages/create-waku-app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-waku-app/package.json b/packages/create-waku-app/package.json index 0e00cc1..11e1269 100644 --- a/packages/create-waku-app/package.json +++ b/packages/create-waku-app/package.json @@ -34,7 +34,7 @@ "ethereum", "dapps" ], - "license": "MIT", + "license": "MIT OR Apache-2.0", "wakuExamples": { "eth-pm": "../../eth-pm", "light-js": "../../light-js", From 440e297c600c7d71c6a4db65c8c9a13d20756ce2 Mon Sep 17 00:00:00 2001 From: weboko Date: Wed, 7 Dec 2022 19:07:57 +0100 Subject: [PATCH 13/14] fix: skip npm i for examples without package.json --- packages/create-waku-app/createApp.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/create-waku-app/createApp.js b/packages/create-waku-app/createApp.js index add5ca6..e7316b0 100644 --- a/packages/create-waku-app/createApp.js +++ b/packages/create-waku-app/createApp.js @@ -61,6 +61,12 @@ function createApp(name, template) { } function runNpmInApp(root) { + const packageJsonPath = path.resolve(root, "package.json"); + + if (!fs.existsSync(packageJsonPath)) { + return; + } + console.log("Installing npm packages."); try { execSync(`npm install --prefix ${root}`, { stdio: "ignore" }); From f846d7cec39fe2c53e0de56b5ba01e74d4575e52 Mon Sep 17 00:00:00 2001 From: weboko Date: Thu, 8 Dec 2022 18:34:38 +0100 Subject: [PATCH 14/14] nit: move to await try/catch --- packages/create-waku-app/build.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/create-waku-app/build.js b/packages/create-waku-app/build.js index 32327f1..5e7d272 100644 --- a/packages/create-waku-app/build.js +++ b/packages/create-waku-app/build.js @@ -12,23 +12,24 @@ async function run() { console.log("Started copying supported Waku examples."); - const copyPromises = supportedExamples.map(([name, relativePath]) => { + const copyPromises = supportedExamples.map(async ([name, relativePath]) => { const resolvedPath = path.resolve(__dirname, relativePath); const destinationPath = path.resolve(examplesFolder, name); - - return fs.copy(resolvedPath, destinationPath, { filter: nodeModulesFiler }).catch((error) => { + + try { + await fs.copy(resolvedPath, destinationPath, { filter: nodeModulesFiler }); + } catch (error) { console.error(`Failed to copy example ${name} to ${destinationPath} with ${error.message}`); throw Error(error.message); - }); + } }); - await Promise.all(copyPromises) - .then(() => { - console.log("Finished copying examples."); - }) - .catch((error) => { - console.error("Failed to copy examples due to " + error.message); - }); + try { + await Promise.all(copyPromises); + console.log("Finished copying examples."); + } catch (error) { + console.error("Failed to copy examples due to " + error.message); + } } function nodeModulesFiler(src) {