diff --git a/README.md b/README.md index 152dc6b9d10..56447e109fa 100644 --- a/README.md +++ b/README.md @@ -76,12 +76,23 @@ library". yarn start:dev ``` -Or, if the server is running: +This will first generate adaptors from your monorepo, then launch the server. + +You can trigger a rebuild with: ``` yarn generate-adaptors -m ``` +Where `-m` means "build from the monorepo. + +To automatically rebuild whenever docs.json changes, run `generate-adaptors` +with watch mode: + +``` +yarn generate-adaptors -w +``` + Ensure that the OPENFN_ADAPTORS_REPO env var is set and points to the local monorepo. diff --git a/generate-adaptors/index.js b/generate-adaptors/index.js index 6e44900c031..7a0da52ce5e 100644 --- a/generate-adaptors/index.js +++ b/generate-adaptors/index.js @@ -1,6 +1,7 @@ const axios = require('axios'); const fs = require('fs'); const path = require('path'); +const chokidar = require('chokidar'); const versions = []; @@ -61,19 +62,11 @@ async function loadAdaptorsDocsFromGithub() { }); } -async function loadAdaptorsDocsFromMonorepo(baseDir) { - console.log('Loading adaptors docs from adaptors monorepo at ', baseDir); - - if (!baseDir) { - throw new Error(`ERROR: monorepo path not found. - -Make sure OPENFN_ADAPTORS_REPO is set in your env`); - } +async function loadAdaptorsDocsFromMonorepo(monorepoPath) { + console.log('Loading adaptors docs from adaptors monorepo', monorepoPath); try { - // Read from tmp not from docs, because otherwise the adaptor - // build script won't work properly - const raw = fs.readFileSync(path.resolve(baseDir, 'tmp/docs.json')); + const raw = fs.readFileSync(monorepoPath, 'utf8'); return JSON.parse(raw); } catch (e) { console.error('Error loading adaptor docs from monerepo'); @@ -208,6 +201,48 @@ function displaySchemaFullSchema(schema) { return '```json \n' + JSON.stringify(schema, null, 4) + '\n```'; } +async function buildAdaptors(monorepoPath) { + const adaptors = await (monorepoPath + ? loadAdaptorsDocsFromMonorepo(monorepoPath) + : loadAdaptorsDocsFromGithub()); + + console.log('Generating adaptors docs via JSDoc...'); + adaptors.map(a => { + if (!a.name) { + console.warn('WARNING: No name for ', a); + return; + } + + const docsBody = generateJsDoc(a); + const readmeBody = generateReadme(a); + const changelogBody = generateChangelog(a); + + const configurationSchemaBody = generateConfigurationSchema(a); + + pushToPaths(a.name); + + fs.writeFileSync(`./adaptors/packages/${a.name}-docs.md`, docsBody); + fs.writeFileSync(`./adaptors/packages/${a.name}-readme.md`, readmeBody); + fs.writeFileSync( + `./adaptors/packages/${a.name}-changelog.md`, + changelogBody + ); + fs.writeFileSync( + `./adaptors/packages/${a.name}-configuration-schema.md`, + configurationSchemaBody + ); + + fs.writeFileSync( + './adaptors/packages/publicPaths.json', + JSON.stringify(filePaths, null, 2) + ); + + console.log(`Done ${a.name} ✓`); + }); + + console.log('Done all adaptors ✓'); +} + module.exports = function (context, { apiUrl }) { return { name: 'adaptors', @@ -220,18 +255,23 @@ module.exports = function (context, { apiUrl }) { '--monorepo ', 'use the adaptors monorepo to load docs metadata' ) + .option('-w', '--watch', 'watch the monorepo docs file for changes') .action(async cmd => { fs.existsSync('./adaptors/packages') || fs.mkdirSync('./adaptors/packages'); let useMonorepo = false; + let watchMonorepo = false; // the monorepo option is suppposed to be written to cmd - // ... but it's not. - // This is a total hack but it works - const last = process.argv.at(-1); - if (last === '-m' || last === '--monorepo') { - useMonorepo = true; + // ... but it's not. So we do it ourselves + for (const a of process.argv) { + if (/(-m|--monorepo)/.test(a)) { + useMonorepo = true; + } else if (/(-w|--watch)/.test(a)) { + useMonorepo = true; + watchMonorepo = true; + } } if (!useMonorepo) { @@ -248,49 +288,36 @@ module.exports = function (context, { apiUrl }) { console.warn('Skipping version list as loading from monorepo'); } - const adaptors = await (useMonorepo - ? loadAdaptorsDocsFromMonorepo(process.env.OPENFN_ADAPTORS_REPO) - : loadAdaptorsDocsFromGithub()); - - console.log('Generating adaptors docs via JSDoc...'); - - adaptors.map(a => { - if (!a.name) { - console.warn('WARNING: No name for ', a); - return; + let monorepoPath = false; + if (useMonorepo) { + if (process.env.OPENFN_ADAPTORS_REPO) { + monorepoPath = path.resolve( + process.env.OPENFN_ADAPTORS_REPO, + // Read from tmp not from docs, because otherwise the adaptor + // build script won't work properly + 'tmp/docs.json' + ); + } else { + if (!monorepoPath) { + throw new Error(`ERROR: monorepo path not found. + +Make sure OPENFN_ADAPTORS_REPO is set in your env`); + } } + } - const docsBody = generateJsDoc(a); - const readmeBody = generateReadme(a); - const changelogBody = generateChangelog(a); - - const configurationSchemaBody = generateConfigurationSchema(a); - - pushToPaths(a.name); - - fs.writeFileSync(`./adaptors/packages/${a.name}-docs.md`, docsBody); - fs.writeFileSync( - `./adaptors/packages/${a.name}-readme.md`, - readmeBody - ); - fs.writeFileSync( - `./adaptors/packages/${a.name}-changelog.md`, - changelogBody - ); - fs.writeFileSync( - `./adaptors/packages/${a.name}-configuration-schema.md`, - configurationSchemaBody - ); - - fs.writeFileSync( - './adaptors/packages/publicPaths.json', - JSON.stringify(filePaths, null, 2) - ); - - console.log(`Done ${a.name} ✓`); - }); - - console.log('Done all adaptors ✓'); + await buildAdaptors(monorepoPath); + if (watchMonorepo) { + const watcher = chokidar.watch(monorepoPath, { + persistent: true, + }); + watcher.on('change', () => { + // change may fire before the write has fully finished + setTimeout(() => { + buildAdaptors(monorepoPath); + }, 500); + }); + } }); }, }; diff --git a/package.json b/package.json index 31cec3b274d..9dad460dd20 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "docusaurus": "docusaurus", "generate-library": "docusaurus generate-library", "generate-adaptors": "docusaurus generate-adaptors", - "start": "docusaurus generate-adaptors && docusaurus start", + "start": "docusaurus generate-adaptors & docusaurus start", "start:dev": "docusaurus generate-adaptors -m && docusaurus start", "start-offline": "docusaurus start", "build": "docusaurus build", @@ -52,6 +52,7 @@ "@types/react": "^17.0.0", "@types/react-helmet": "^6.1.0", "@types/react-router-dom": "^5.1.7", + "chokidar": "^3.6.0", "typescript": "^4.1.3" }, "resolutions": { diff --git a/yarn.lock b/yarn.lock index 5d42d182e5a..df77f7e6670 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2571,6 +2571,7 @@ __metadata: "@types/react": ^17.0.0 "@types/react-helmet": ^6.1.0 "@types/react-router-dom": ^5.1.7 + chokidar: ^3.6.0 clsx: ^1.1.1 compare-versions: ^5.0.1 date-fns: 2.21.3 @@ -4194,7 +4195,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.4.2, chokidar@npm:^3.5.3": +"chokidar@npm:^3.4.2, chokidar@npm:^3.5.3, chokidar@npm:^3.6.0": version: 3.6.0 resolution: "chokidar@npm:3.6.0" dependencies: