Skip to content

Commit

Permalink
feat(cli): tools to make managing easy (#59)
Browse files Browse the repository at this point in the history
* feat(utils): create new affiliation files

* chore(custom): cli

ability to include comma seperated list

* fix(custom): cli

move to esm

* chore(custom): cli

add bin object

* chore(cli): add cli scope

add bin object

* feat(cli): combine affiliations to json file

add bin object

* feat(cli): save local data file

* feat(cli): create data loader file

* fix(cli): remove minified replace function

* chore(deps): add inquirer

* feat(cli): update affiliation

* fix(cli): run inquirer if any option is missing

* feat(cli): add new signature object

* chore(cli): move commands to own directory

* feat(cli): parse data function

* feat(cli): read file function

* feat(cli): update date file function

* chore(cli): sorted onject

* feat(cli): alaphabetically sort object

* chore(cli): moved file locations

* chore(cli): ignore test command

* chore(cli): update cli call command

* chore(data): alphabetically sort object

* chore(data): local data file
  • Loading branch information
PaleBluDot authored May 20, 2024
1 parent 221553d commit a80d18d
Show file tree
Hide file tree
Showing 19 changed files with 765 additions and 70 deletions.
2 changes: 1 addition & 1 deletion .config/commitizen.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const types = [
},
];

const scopes = ["components", "config", "data", "deps", "layout", "media", "partials", "styles", "templates", "test", "utils"].map((name) => ({
const scopes = ["components", "config", "cli", "data", "deps", "layout", "media", "partials", "styles", "templates", "test", "utils"].map((name) => ({
name,
}));

Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# dependencies
node_modules/

# test files
.vscode/settings.json
src/_data/affiliations/xx.js
src/**/**/xx.js
src/test/xx.test.js
bin/commands/testCommand.mjs

# build artifacts
build/
Expand Down
49 changes: 49 additions & 0 deletions bin/cli.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env node

import { program } from "commander";
import addNewAffiliation from "./commands/addNewAffiliation.mjs";
import addNewSignature from "./commands/addNewSignature.mjs";
import saveLocalData from "./commands/saveLocalData.mjs";
import createDataLoader from "./commands/createDataLoader.mjs";
import updateAffiliation from "./commands/updateAffiliation.mjs";

program
.command("add [name]")
.description("Add a new affiliation")
.action((name) => addNewAffiliation(name));

program
.command("signature [name]")
.description("Create new signature object")
.action((name) => addNewSignature(name));

program
.command("save [name]")
.description("Create local json data file")
.option("-l, --location <path>", "location to save the file")
.action((name, cmdObj) => {
const location = cmdObj.location;
saveLocalData(name, location);
});

program
.command("create [location]")
.description("Create Sailthru data loader file")
.action((location) => createDataLoader(location));

program
.command("update [options...]")
.description("Update the value for a key")
.option("-a, --affiliation <type>", "affiliation name")
.option("-k, --key <type>", "key to replace")
.option("-v, --value <type>", "new value")
.action((optionsArgs, cmdObj) => {
const options = {
affiliation: cmdObj.affiliation,
key: cmdObj.key,
value: cmdObj.value,
};
updateAffiliation(options);
});

program.parse(process.argv);
101 changes: 101 additions & 0 deletions bin/commands/addNewAffiliation.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import fs from "fs";
import path, { dirname } from "path";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

function addNewAffiliation(names) {
if (!names) {
console.error("Names are required");
return;
}

const dirPath = path.join(__dirname, "../../src/_data/affiliations");

if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}

const namesArray = names.includes(",") ? names.split(",") : [names];

namesArray.forEach((name) => {
const filePath = path.join(dirPath, `${name}.js`);

const template = `const data = {
address1: "",
address2: "",
affiliation_name: "",
donation_url: "",
facebook_url: "",
instagram_url: "",
logo_url: "",
logo_width: "150",
signatures: {
advo: {
title: "Chief Political and Advocacy Officer",
name: "",
pronouns: "",
headshot: "",
},
comms: {
title: "Chief Communications and Marketing Officer",
name: "",
pronouns: "",
headshot: "",
},
custom1: {
title: "",
name: "",
pronouns: "",
headshot: "",
},
custom2: {
title: "",
name: "",
pronouns: "",
headshot: "",
},
custom3: {
title: "",
name: "",
pronouns: "",
headshot: "",
},
dev: {
title: "Chief Development Officer",
name: "",
pronouns: "",
headshot: "",
},
ed: {
title: "Executive Director",
name: "",
pronouns: "",
headshot: "",
},
legal: {
title: "Legal Director",
name: "",
pronouns: "",
headshot: "",
},
},
twitter_url: "",
website_url: "",
};
module.exports = data;
`;

fs.writeFile(filePath, template, (err) => {
if (err) {
console.error(`Error creating file: ${err}`);
} else {
console.log(`Created new affiliation file at ${filePath}`);
}
});
});
}

export default addNewAffiliation;
66 changes: 66 additions & 0 deletions bin/commands/addNewSignature.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import { createRequire } from "module";
import sortObject from "../lib/sortObject.mjs";

const require = createRequire(import.meta.url);

function toJS(object) {
return `const data = ${sortObject(object)};\n\nmodule.exports = data;`;
}

function createSailthruSigVariable(sig) {
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const filePath = path.join(__dirname, "../lib/sailthruVariables.mjs");

let sailthruVariables = fs.readFileSync(filePath, "utf8");

const sailthruSignatureVariables = `
{${sig}_name = data[affiliation]['signatures']['${sig}']['name']}
{${sig}_title = data[affiliation]['signatures']['${sig}']['title']}
{${sig}_pronouns = data[affiliation]['signatures']['${sig}']['pronouns']}
{${sig}_headshot = data[affiliation]['signatures']['${sig}']['headshot']}
`;

sailthruVariables = sailthruVariables.replace("`;\n\nexport default sailthruVariables;", sailthruSignatureVariables + "`;\n\nexport default sailthruVariables;");

fs.writeFileSync(filePath, sailthruVariables);
}

export default function addNewSignature(name) {
if (!name) {
console.error("Name is required");
return;
}

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const directory = path.join(__dirname, "../../src/_data/affiliations");
const files = fs.readdirSync(directory);

createSailthruSigVariable(name);

for (const file of files) {
const filePath = path.join(directory, file);
let data;
try {
data = require(filePath);
} catch (err) {
console.error("Failed to import module", err);
continue;
}

if (!data.signatures) {
data.signatures = {};
}

data.signatures[name] = {
title: "",
name: "",
pronouns: "",
headshot: "",
};

fs.writeFileSync(filePath, toJS(data));
}
}
19 changes: 19 additions & 0 deletions bin/commands/createDataLoader.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import fs from "fs";
import path from "path";
import getCombinedData from "../lib/combineAffiliation.mjs";
import sailthruVariables from "../lib/sailthruVariables.mjs";

export default function createLoaderFile(location = "build/data") {
getCombinedData().then((data) => {
const minifiedJson = "{data = " + JSON.stringify(data) + "}";
const distPath = path.join(location, "dataLoader.min.json");
let combineData = minifiedJson + sailthruVariables;

fs.mkdirSync(location, { recursive: true });

fs.writeFile(distPath, combineData, (err) => {
if (err) throw err;
console.log("HTML Content data written to:", distPath);
});
});
}
15 changes: 15 additions & 0 deletions bin/commands/saveLocalData.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import fs from "fs";
import path from "path";
import getCombinedData from "../lib/combineAffiliation.mjs";

export default function saveCombinedData(name = "dataLoader", location = "src/_data") {
getCombinedData().then((data) => {
const savePath = path.join(location, `${name}.json`);
const jsonData = JSON.stringify(data, null, 2);

fs.mkdirSync(location, { recursive: true });

fs.writeFileSync(savePath, jsonData);
console.log("Data saved to", savePath);
});
}
94 changes: 94 additions & 0 deletions bin/commands/updateAffiliation.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import fs from "fs";
import path, { dirname } from "path";
import { fileURLToPath } from "url";
import inquirer from "inquirer";
import util from "util";
import updateDataFile from "../lib/updateDataFile.mjs";

const __dirname = dirname(fileURLToPath(import.meta.url));
const affiliationsDir = path.join(__dirname, "../../src/_data/affiliations");

export default function updateAffiliation(options = {}) {
const files = fs.readdirSync(affiliationsDir);
const affiliations = files.map((file) => path.basename(file, ".js"));

inquirer
.prompt([
{
type: "list",
name: "affiliation",
message: "Select the affiliation to update:",
choices: affiliations,
default: options.affiliation,
when: () => !options.affiliation,
},
])
.then((answers) => {
const affiliation = options.affiliation || answers.affiliation;
const filePath = path.join(affiliationsDir, `${affiliation}.js`);

import(filePath).then((content) => {
const keys = Object.keys(content.default);

inquirer
.prompt([
{
type: "list",
name: "key",
message: "Select the key to replace:",
choices: keys,
default: options.key,
when: () => !options.key,
},
{
type: "input",
name: "value",
message: "Enter the new value:",
default: options.value,
when: (answers2) => !options.value && answers2.key !== "signatures",
},
])
.then((answers2) => {
const key = options.key || answers2.key;
const value = options.value || answers2.value;

if (key === "signatures") {
const signatureKeys = Object.keys(content.default.signatures);

inquirer
.prompt([
{
type: "list",
name: "signatureKey",
message: "Select the signature to replace:",
choices: signatureKeys,
},
])
.then((answers3) => {
const signatureProperties = Object.keys(content.default.signatures[answers3.signatureKey]);

inquirer
.prompt([
{
type: "list",
name: "signatureProperty",
message: "Select the property to replace:",
choices: signatureProperties,
},
{
type: "input",
name: "value",
message: "Enter the new value:",
},
])
.then((answers4) => {
updateDataFile(affiliation, `signatures.${answers3.signatureKey}.${answers4.signatureProperty}`, answers4.value);
});
});
} else {
updateDataFile(affiliation, key, value);
}
});
});
});
}
25 changes: 25 additions & 0 deletions bin/lib/combineAffiliation.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import fs from "fs";
import path, { dirname } from "path";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const affiliationsDir = path.join(__dirname, "../../src/_data/affiliations");
const files = fs.readdirSync(affiliationsDir);

function getCombinedData() {
let combinedData = {};

const imports = files.map((file) => {
const filePath = path.join(affiliationsDir, file);
return import(filePath).then((data) => {
const affiliation = path.basename(file, path.extname(file));
combinedData[affiliation] = data.default;
});
});

return Promise.all(imports).then(() => combinedData);
}

export default getCombinedData;
Loading

0 comments on commit a80d18d

Please sign in to comment.