From bc95362a2d693f0a6e4b817a7f9b724fe1eba268 Mon Sep 17 00:00:00 2001 From: beaspider Date: Fri, 3 Jul 2020 17:55:12 +0100 Subject: [PATCH 1/2] Add support for syncing pages using update and deploy commands --- .gitignore | 2 ++ Dockerfile | 5 +++ Makefile | 11 ++++++ README.md | 16 +++++++++ docker-compose.yml | 15 ++++++++ src/actions/campaigns.js | 18 ++++++++++ src/actions/sync.js | 76 ++++++++++++++++++++++++++++++++++++++++ src/deploy.js | 26 ++++++++++++-- src/init.js | 5 ++- src/update.js | 5 ++- 10 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 docker-compose.yml diff --git a/.gitignore b/.gitignore index 56656af..688be4f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ raisely.json # dev folders stylesheets components +pages .raisely.json +.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0f2d4a5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,5 @@ +FROM node:12 + +WORKDIR /var/local + +CMD ["tail", "-f", "/dev/null"] \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..709c4e1 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +.PHONY: init update deploy + +init: + npm install + node ./bin/raisely init + +update: + node ./bin/raisely update + +deploy: + node ./bin/raisely deploy diff --git a/README.md b/README.md index d671151..1d8b182 100644 --- a/README.md +++ b/README.md @@ -46,3 +46,19 @@ With these environment variables set, run: `raisely deploy`. This will sync your ## Developing Contributions are welcome. The project is built with `commander`, `inquirer` and `ora` with a basic module structure. + +### Local Development With Docker + +Create a `.env` file in this directory containing: + +RAISELY_TOKEN= + +RAISELY_CAMPAIGNS= + +then run `docker-compose up` from this directory. + +In a new terminal window connect to the docker container: + +`docker exec -it raisely-cli /bin/bash` + +A Makefile provides tasks \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..812c497 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +version: '2' + +services: + + raisely_cli: + container_name: "raisely_cli" + build: + context: . + dockerfile: Dockerfile + volumes: + - ".:/var/local" + environment: + - RAISELY_TOKEN=${RAISELY_TOKEN} + - RAISELY_CAMPAIGNS=${RAISELY_CAMPAIGNS} + restart: always diff --git a/src/actions/campaigns.js b/src/actions/campaigns.js index 18e6dbf..70f1373 100644 --- a/src/actions/campaigns.js +++ b/src/actions/campaigns.js @@ -95,3 +95,21 @@ export async function updateStyles({ path, files, css }, config) { config.apiUrl ); } + + +export async function updatePage(page, config) { + return await api( + { + path: `/pages/${page.uuid}?private=true`, + method: "PATCH", + json: { + data: page.data + }, + auth: { + bearer: config.token + } + }, + config.apiUrl + ); + +} \ No newline at end of file diff --git a/src/actions/sync.js b/src/actions/sync.js index f4ccd16..842c456 100644 --- a/src/actions/sync.js +++ b/src/actions/sync.js @@ -120,3 +120,79 @@ export async function syncComponents(config, workDir, filter) { return error(e, loader); } } + +export async function syncPages(config, workDir) { + const directory = path.join(workDir, "pages"); + if (!fs.existsSync(directory)) { + fs.mkdirSync(directory); + } + + const loader = ora("Downloading campaign pages...").start(); + try { + for (const uuid of config.campaigns) { + const campaign = await api( + { + path: `/campaigns/${uuid}?private=true`, + auth: { + bearer: config.token + } + }, + config.apiUrl + ); + + const campaignDir = path.join(directory, campaign.data.path); + + if (!fs.existsSync(campaignDir)) { + fs.mkdirSync(campaignDir); + } + + const pages = await api( + { + path: `/campaigns/${uuid}/pages`, + qs: { + private: 1, + limit: 100 + }, + auth: { + bearer: config.token + } + }, + config.apiUrl + ); + + for (const page of pages.data) { + fs.writeFileSync( + path.join(campaignDir, `${page.internalTitle}.json`), + JSON.stringify( + { + uuid: page.uuid, + data: { // these are the editable page fields + title: page.title, + internalTitle: page.internalTitle, + body: page.body, + path: page.path, + status: page.status, + provider: page.provider, + condition: page.condition, + image: page.image, + metaTitle: page.metaTitle, + metaDescription: page.metaDescription, + socialTitle: page.socialTitle, + socialDescription: page.socialDescription + } + }, + null, + 4 + ) + ); + } + + } + + loader.succeed(); + } catch (e) { + console.log(e); + return error(e, loader); + } + +} \ No newline at end of file diff --git a/src/deploy.js b/src/deploy.js index 568ecc6..6d85306 100644 --- a/src/deploy.js +++ b/src/deploy.js @@ -5,7 +5,7 @@ import fs from "fs"; import path from "path"; import { welcome, log, br, error } from "./helpers"; -import { buildStyles, getCampaign } from "./actions/campaigns"; +import { buildStyles, getCampaign, updatePage } from "./actions/campaigns"; import { updateComponentFile, updateComponentConfig @@ -28,7 +28,7 @@ export default function deploy(program) { br(); } log( - `You will overwrite the styles and components in your campaign.`, + `You will overwrite the styles, components and pages in your campaign.`, "white" ); br(); @@ -94,6 +94,28 @@ export default function deploy(program) { loader.succeed(); } + // upload campaign pages + for (const campaignUuid of config.campaigns) { + const loader = ora(`Uploading pages for ${campaignUuid}`).start(); + const campaign = await getCampaign( + { uuid: campaignUuid }, + config.token, + config + ); + + const pagesDir = path.join(process.cwd(), "pages"); + const campaignDir = path.join(pagesDir, `${campaign.data.path}`); + + for (const file of fs.readdirSync(campaignDir)) { + const pageData = JSON.parse(fs.readFileSync( + path.join(campaignDir, file), + "utf8" + )) + await updatePage(pageData, config); + } + loader.succeed(); + } + br(); log(`All done!`); }); diff --git a/src/init.js b/src/init.js index 7007cf2..b494c92 100644 --- a/src/init.js +++ b/src/init.js @@ -5,7 +5,7 @@ import ora from "ora"; import { welcome, log, br, error } from "./helpers"; import { login } from "./actions/auth"; import { getCampaigns } from "./actions/campaigns"; -import { syncStyles, syncComponents } from "./actions/sync"; +import { syncStyles, syncComponents, syncPages } from "./actions/sync"; import { saveConfig } from "./config"; export default function init(program) { @@ -95,6 +95,9 @@ export default function init(program) { // sync down custom components await syncComponents(config, process.cwd()); + // sync down pages + await syncPages(config, process.cwd()); + br(); log("All done! You can start development by running:", "green"); br(); diff --git a/src/update.js b/src/update.js index 27e1869..1e464e4 100644 --- a/src/update.js +++ b/src/update.js @@ -2,7 +2,7 @@ import chalk from "chalk"; import inquirer from "inquirer"; import { welcome, log, br, error } from "./helpers"; -import { syncStyles, syncComponents } from "./actions/sync"; +import { syncStyles, syncComponents, syncPages } from "./actions/sync"; import { loadConfig } from "./config"; export default function update(program) { @@ -48,6 +48,9 @@ export default function update(program) { // sync down custom components await syncComponents(config, process.cwd()); + // sync down pages + await syncPages(config, process.cwd()); + br(); log( `All done! Run ${chalk.bold.underline.white( From 91590fc5c338ff797f827f16b68c7e0c4a52ead6 Mon Sep 17 00:00:00 2001 From: beaspider Date: Fri, 3 Jul 2020 19:05:29 +0100 Subject: [PATCH 2/2] Add support for syncing pages to the start command --- Makefile | 8 ++++++-- README.md | 18 +++++++++--------- src/start.js | 24 +++++++++++++++++++++++- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 709c4e1..d2194a8 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: init update deploy +.PHONY: init update deploy start init: npm install @@ -8,4 +8,8 @@ update: node ./bin/raisely update deploy: - node ./bin/raisely deploy + node ./bin/raisely deploy + +start: + node ./bin/raisely start + diff --git a/README.md b/README.md index 1d8b182..0a0ccb8 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,13 @@ ![Raisely logo](https://raisely-themes.imgix.net/raisely/brand.raisely.svg) -The Raisely CLI is used to power local development of Raisely themes, syncing custom components and campaign styles to your local machine. +The Raisely CLI is used to power local development of Raisely themes, syncing custom components, campaign styles and pages to your local machine. For more about Raisely, see ## Overview -The Raisely CLI allows for fast and easy development on the Raisely platform. The CLI allows you to connect a directory on your local computer to a Raisely account. With the CLI you can update campaign stylesheets, and edit and create custom React components. +The Raisely CLI allows for fast and easy development on the Raisely platform. The CLI allows you to connect a directory on your local computer to a Raisely account. With the CLI you can update campaign stylesheets, pages and edit and create custom React components. The CLI is built on Node.js, so you'll need Node.js installed to use it. @@ -26,9 +26,9 @@ For other issues, [submit a support ticket](mailto:support@raisely.com). ## Commands - `raisely init` - start a new Raisely project, authenticate and sync your campaigns -- `raisely update` - update local copies of styles and components from the API +- `raisely update` - update local copies of styles, pages and components from the API - `raisely create [name]` - create a new custom component, optionally add the component name to the command (otherwise you will be asked for one) -- `raisely start` - starts watching for and uploading changes to styles and components +- `raisely start` - starts watching for and uploading changes to styles, pages and components ## CI/CD Usage @@ -41,7 +41,7 @@ Raisely CLI supports the following environment variables: _Note: All components are always synced, when they're present in the directory your syncing_ -With these environment variables set, run: `raisely deploy`. This will sync your local directory to the remote Raisely account, overwriting the styles and components on the destination campaign. +With these environment variables set, run: `raisely deploy`. This will sync your local directory to the remote Raisely account, overwriting the styles, pages and components on the destination campaign. ## Developing @@ -49,11 +49,11 @@ Contributions are welcome. The project is built with `commander`, `inquirer` and ### Local Development With Docker -Create a `.env` file in this directory containing: +Create a `.env` file in this directory containing the required environment variables: -RAISELY_TOKEN= +RAISELY_TOKEN= -RAISELY_CAMPAIGNS= +RAISELY_CAMPAIGNS= then run `docker-compose up` from this directory. @@ -61,4 +61,4 @@ In a new terminal window connect to the docker container: `docker exec -it raisely-cli /bin/bash` -A Makefile provides tasks \ No newline at end of file +A Makefile provides tasks diff --git a/src/start.js b/src/start.js index 9b4ccd2..8636c97 100644 --- a/src/start.js +++ b/src/start.js @@ -5,7 +5,7 @@ import path from "path"; import glob from "glob-promise"; import { welcome, log, br, error } from "./helpers"; -import { updateStyles, buildStyles } from "./actions/campaigns"; +import { updateStyles, buildStyles, updatePage } from "./actions/campaigns"; import { updateComponentFile, updateComponentConfig @@ -33,6 +33,7 @@ export default function start(program) { // watch folders const stylesDir = path.join(process.cwd(), "stylesheets"); const componentsDir = path.join(process.cwd(), "components"); + const pagesDir = path.join(process.cwd(), "pages"); fs.watch( stylesDir, { encoding: "utf8", recursive: true }, @@ -99,5 +100,26 @@ export default function start(program) { loader.succeed(); } ); + + fs.watch( + pagesDir, + { encoding: "utf8", recursive: true }, + async (eventType, filename) => { + const loader = ora(`Saving ${filename}`).start(); + try { + const pageData = JSON.parse(fs.readFileSync( + path.join(pagesDir, `${filename}`), + "utf8" + )) + await updatePage(pageData, config); + } catch (e) { + return error(e, loader); + } + + loader.succeed(); + } + ); + + }); }