Skip to content

Commit

Permalink
Merge pull request #30 from flotiq/feature/25535-codegen-ts-extension…
Browse files Browse the repository at this point in the history
…-for-content-publishing

#25535 codegen ts extension for content publishing
  • Loading branch information
KrzysztofBrylski authored Oct 25, 2024
2 parents df4049b + d3d2f53 commit d972b6e
Show file tree
Hide file tree
Showing 7 changed files with 313 additions and 232 deletions.
38 changes: 29 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Go to this [JSFiddle](https://jsfiddle.net/o5rafnpw/1/) to see a (limited) demo.

## Quickstart

```
```bash
npx flotiq-codegen-ts generate
```

Expand All @@ -39,9 +39,9 @@ const eventList = await flotiq.EventAPI.list({limit: 100});

## Usage in JS project

If you wish to use `flotiqApi` in JS project you can use `flotiq-codegen-ts` with `--compiled-js` flag
If you wish to use `flotiqApi` in JS project you can use `flotiq-codegen-ts` with `--compiled-js`/`-c` flag

```
```bash
npx flotiq-codegen-ts generate --compiled-js
```

Expand All @@ -65,26 +65,46 @@ The `flotiq-codegen-ts` tool offers a feature to continuously monitor changes in
automatically regenerates the SDK whenever changes are detected, ensuring that developers always have the most
up-to-date data models in their IDE without manual intervention.

The `--watch` option for `flotiq-codegen-ts` ensures your SDK stays up-to-date by automatically monitoring and regenerating
The `--watch`/`-w` option for `flotiq-codegen-ts` ensures your SDK stays up-to-date by automatically monitoring and regenerating
based on content changes.

If you want to see changes made in Flotiq by your content editor in your IDE, use `flotiq-codegen-ts` with `--watch`
If you want to see changes made in Flotiq by your content editor in your IDE, use `flotiq-codegen-ts` with `--watch`/`-w`
flag

```
```bash
npx flotiq-codegen-ts generate --watch
```

or, if you want your SDK to be directly compiled to JavaScript use `flotiq-codegen-ts` with flags `--watch`
and `--compiled-js`
or, if you want your SDK to be directly compiled to JavaScript use `flotiq-codegen-ts` with flags `--watch`/`-w`
and `--compiled-js`/`-c`

```
```bash
npx flotiq-codegen-ts generate --watch --compiled-js
```

Now, `flotiq-codegen-ts` will check for changes in your Flotiq content every 10 seconds. If changes are detected, it will
automatically regenerate your SDK to reflect the updates.

## Surpressing output messages

If you don't want to receive output messages, pass `--silent`/`-s` option to limit number of logs. This option assumes, that the generator cannot read api key from `.env.*` file and will not ask for key in the console.

```bash
npx flotiq-codegen-ts generate --silent
```

This is especially useful when you are using generator with other automation tools or you are running generate function by hand.

## Node.js api

You can use command handler in your scripts by importing command handler

```javascript
const {handler} = require('flotiq-codegen-ts/commands/generate');

await handler({flotiqApiKey: 'test-ro-key', watch: false, silent: false, compiledJs: false});
```

## Developing

To start developing this project, follow these steps:
Expand Down
186 changes: 186 additions & 0 deletions commands/generate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
const inquirer = require('inquirer');
const buildToJs = require("../src/build_to_js");
const cleanDuplicateImport = require("../src/clean_duplicate_import");
const fs = require('fs');
const fce = require('fs-extra');
const {checkForChanges, getWorkingPath, lambdaInvoke, loader, confirm} = require("../src/helpers");
const admZip = require('adm-zip');
const path = require('path');
const dotenvFlow = require('dotenv-flow');

const envName = "FLOTIQ_API_KEY";

const compileToJsFlag = "compiled-js";
const apiKeyFlag = "flotiq-api-key";
const watchFlag = "watch";
const silentFlag = "silent";
const watchInterval = 10000;

const CLI_GREEN = "\x1b[32m%s\x1b[0m";
const CLI_BLUE = "\x1b[36m%s\x1b[0m";

const LAMBDA_URL = `https://0c8judkapg.execute-api.us-east-1.amazonaws.com/default/codegen-ts`;

async function generateSDK(apiKey, compileToJs, logger) {
try {
logger.log('Generating client from schema...');

// Generate command
const lambdaUrl = `${LAMBDA_URL}?token=${apiKey}`;
const zip = new admZip(await lambdaInvoke(lambdaUrl, logger));
const tmpPath = getWorkingPath();
const tmpSDKPath = `${tmpPath}/flotiqApi`;
const outputPath = path.join(process.cwd(), 'flotiqApi');

logger.log(`Extracting SDK client to tmp dir '${tmpPath}'...`);
zip.extractAllTo(tmpSDKPath);
cleanDuplicateImport(tmpSDKPath);

if (compileToJs) {
logger.log('Compiling to JavaScript...');
buildToJs(tmpSDKPath, logger);
}

if (fs.existsSync(outputPath)) {
logger.log(`Found existing SDK in '${outputPath}' - cleaning up...`);
fce.removeSync(outputPath);
}

logger.log(`Moving SDK to '${outputPath}'...`);
fce.moveSync(tmpSDKPath, outputPath);
fce.removeSync(tmpPath);

logger.log(CLI_GREEN, 'Client generated successfully!');
logger.log(CLI_GREEN, 'You can start using your Flotiq SDK');
logger.log(CLI_BLUE, 'Read more: https://github.com/flotiq/flotiq-codegen-ts');

} catch (error) {
logger.error('An error occurred:', error);
process.exit(1);
}
}

async function watchChanges(apiKey, compileToJs, logger) {
const configFile = path.join(__dirname, '../src/codegen-ts-watch-config.json');
const data = await checkForChanges(apiKey, logger);
if (!fce.existsSync(configFile)) {
fce.createFileSync(configFile);
fce.writeJsonSync(configFile, data);
}

const configData = fce.readJsonSync(configFile);

if (JSON.stringify(data) === JSON.stringify(configData)) {
return;
}

loader.stop();
loader.succeed('Detected changes in content!')
logger.log(CLI_GREEN, 'Detected changes in content!');

fce.writeJsonSync(configFile, data);
await generateSDK(apiKey, compileToJs, logger);
loader.start();
}

const silentLogger = {
log: () => { },
error: () => { },
warn: () => { },
info: () => { },
debug: () => { },
};

/**
* Run generation command
* @param {{flotiqApiKey: string, watch: boolean, silent: boolean, compiledJs: boolean}} argv
* @returns
*/
async function main(argv) {
let apiKey = argv.flotiqApiKey || process.env[envName];
const silent = argv.silent;
const logger = silent ? silentLogger : console;
const compileToJs = argv.compiledJs;
const watch = argv.watch;

if (!apiKey && !silent) {
const localEnv = dotenvFlow.parse(
dotenvFlow.listFiles({
path: process.cwd(),
})
);

if (localEnv[envName]) {
let query = await confirm(`${envName} found \n Do you want to use API key from env file ?`)
if (query) {
//using API key from file
apiKey = localEnv[envName];
}
}
}

if(!apiKey && !silent) {
const answers = await inquirer.prompt([{
type: 'input',
name: 'apiKey',
message: 'Please enter your Flotiq API key:',
validate: input => !!input || 'API key cannot be empty.'
}]);

apiKey = answers.apiKey;
}



if (!watch) {
await generateSDK(apiKey, compileToJs, logger);
return;
}

loader.start();
await watchChanges(apiKey, compileToJs, logger);
setInterval(
() => watchChanges(apiKey, compileToJs, logger),
watchInterval,
apiKey,
compileToJs
);
}

module.exports = {
command: 'generate [options]',
describe: 'Generate api integration for your Flotiq project',
builder: (yargs) => {
return yargs
.option(apiKeyFlag, {
description: "Flotiq API key",
alias: "",
type: "string",
default: "",
demandOption: false,
})
.option(watchFlag, {
description: "Listen for changes in Flotiq Api Schema, and regenerate SDK after detected change",
alias: "w",
type: "boolean",
default: false,
demandOption: false,
})
.option(silentFlag, {
description: "Suppress console output. Assumes no for all prompts.",
alias: "s",
type: "boolean",
default: false,
demandOption: false,
})
.option(compileToJsFlag, {
description: "Generates Fetch API integration compiled to JavaScript",
alias: "c",
type: "boolean",
default: false,
demandOption: false,
});
},
handler: main,
generateSDK
}
Loading

0 comments on commit d972b6e

Please sign in to comment.