Skip to content

Commit

Permalink
Add support for rendering the prompt-screen's settings (#998)
Browse files Browse the repository at this point in the history
  • Loading branch information
ramya18101 authored Dec 9, 2024
1 parent 04c5b05 commit 66f0b01
Show file tree
Hide file tree
Showing 12 changed files with 484 additions and 28 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"homepage": "https://github.com/auth0/auth0-deploy-cli#readme",
"dependencies": {
"ajv": "^6.12.6",
"auth0": "^4.14.0",
"auth0": "^4.15.0",
"dot-prop": "^5.2.0",
"fs-extra": "^10.1.0",
"global-agent": "^2.1.12",
Expand Down
41 changes: 39 additions & 2 deletions src/context/directory/handlers/prompts.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import path from 'path';
import { ensureDirSync, writeFileSync } from 'fs-extra';
import { constants, loadFileAndReplaceKeywords } from '../../../tools';
import { dumpJSON, existsMustBeDir, isFile, loadJSON } from '../../../utils';
import { getFiles, dumpJSON, existsMustBeDir, isFile, loadJSON } from '../../../utils';
import { DirectoryHandler } from '.';
import DirectoryContext from '..';
import { ParsedAsset } from '../../../types';
Expand All @@ -15,6 +15,7 @@ import {
Prompts,
PromptSettings,
ScreenConfig,
ScreenRenderer,
} from '../../../tools/auth0/handlers/prompts';

type ParsedPrompts = ParsedAsset<'prompts', Prompts>;
Expand All @@ -29,6 +30,9 @@ const getCustomTextFile = (promptsDirectory: string) =>

const getPartialsFile = (promptsDirectory: string) => path.join(promptsDirectory, 'partials.json');

const getScreenRenderSettingsDir = (promptsDirectory: string) =>
path.join(promptsDirectory, constants.PROMPTS_SCREEN_RENDER_DIRECTORY);

function parse(context: DirectoryContext): ParsedPrompts {
const promptsDirectory = getPromptsDirectory(context.filePath);
if (!existsMustBeDir(promptsDirectory)) return { prompts: null }; // Skip
Expand Down Expand Up @@ -84,11 +88,31 @@ function parse(context: DirectoryContext): ParsedPrompts {
}, {} as Record<CustomPartialsPromptTypes, Record<CustomPartialsScreenTypes, Record<string, string>>>);
})();

const screenRenderers = (() => {
const screenRenderSettingsDir = getScreenRenderSettingsDir(promptsDirectory);
if (!existsMustBeDir(screenRenderSettingsDir)) return [];

const screenSettingsFiles = getFiles(screenRenderSettingsDir, ['.json']);

const renderSettings: ScreenRenderer[] = screenSettingsFiles.map((f) => {
const renderSetting = {
...loadJSON(f, {
mappings: context.mappings,
disableKeywordReplacement: context.disableKeywordReplacement,
}),
};
return renderSetting as ScreenRenderer;
});

return renderSettings as ScreenRenderer[];
})();

return {
prompts: {
...promptsSettings,
customText,
partials,
screenRenderers,
},
};
}
Expand All @@ -98,7 +122,7 @@ async function dump(context: DirectoryContext): Promise<void> {

if (!prompts) return;

const { customText, partials, ...promptsSettings } = prompts;
const { customText, partials, screenRenderers, ...promptsSettings } = prompts;

const promptsDirectory = getPromptsDirectory(context.filePath);
ensureDirSync(promptsDirectory);
Expand Down Expand Up @@ -144,6 +168,19 @@ async function dump(context: DirectoryContext): Promise<void> {
}, {} as CustomPartialsConfig);

dumpJSON(partialsFile, transformedPartials);

if (!screenRenderers) return;
const screenRenderSettingsDir = getScreenRenderSettingsDir(promptsDirectory);
ensureDirSync(screenRenderSettingsDir);

for (let index = 0; index < screenRenderers.length; index++) {
const screenRenderersSetting = screenRenderers[index];
delete screenRenderersSetting.tenant;
const fileName = `${screenRenderersSetting.prompt}_${screenRenderersSetting.screen}.json`;
const screenSettingsFilePath = path.join(screenRenderSettingsDir, fileName);

dumpJSON(screenSettingsFilePath, screenRenderersSetting);
}
}

const promptsHandler: DirectoryHandler<ParsedPrompts> = {
Expand Down
117 changes: 113 additions & 4 deletions src/context/yaml/handlers/prompts.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,132 @@
import path from 'path';
import { ensureDirSync, writeFileSync } from 'fs-extra';
import { GetRendering200Response } from 'auth0';
import { YAMLHandler } from '.';
import YAMLContext from '..';
import { constants } from '../../../tools';
import { ParsedAsset } from '../../../types';
import { Prompts } from '../../../tools/auth0/handlers/prompts';
import { Prompts, ScreenRenderer } from '../../../tools/auth0/handlers/prompts';
import { loadJSON } from '../../../utils';
import log from '../../../logger';

type ParsedPrompts = ParsedAsset<'prompts', Prompts>;
// Type for the screen render array
type ScreenRenderYAML = Array<{
[prompt: string]: {
[screen: string]: string; // filename
};
}>;

const getPromptsDirectory = (filePath: string) => path.join(filePath, constants.PROMPTS_DIRECTORY);

const loadScreenRenderers = (
context: YAMLContext,
screenRenderArray: ScreenRenderYAML
): GetRendering200Response[] => {
// Array to store loaded renderers
const loadedRenderers: GetRendering200Response[] = [];

screenRenderArray.forEach((promptEntry) => {
// Get the prompt (there will be only one key in each entry)
const prompt = Object.keys(promptEntry)[0];

const screens = promptEntry[prompt];

Object.entries(screens).forEach(([, fileName]) => {
const filePath = fileName;

try {
const rendererFile = path.join(context.basePath, filePath);

const rendererData = loadJSON(rendererFile, {
mappings: context.mappings,
disableKeywordReplacement: context.disableKeywordReplacement,
});

// Add to the loadedRenderers array
loadedRenderers.push(rendererData);
} catch (error) {
log.error(`Error loading file ${fileName}:`, error);
}
});
});

return loadedRenderers;
};

async function parse(context: YAMLContext): Promise<ParsedPrompts> {
const { prompts } = context.assets;
if (!prompts) return { prompts: null };

if (prompts.screenRenderers && prompts.screenRenderers.length > 0) {
const screenRendersYAML = prompts.screenRenderers as ScreenRenderYAML;
prompts.screenRenderers = loadScreenRenderers(context, screenRendersYAML);
}

return {
prompts,
};
}

const dumpScreenRenderers = (context: YAMLContext, screenRenderers: ScreenRenderer[]) => {
const screenRenderArray: ScreenRenderYAML = [];

const promptsDirectory = getPromptsDirectory(context.basePath);
ensureDirSync(promptsDirectory);

// Create the directory for render settings if it doesn't exist
const renderSettingsDir = path.join(promptsDirectory, constants.PROMPTS_SCREEN_RENDER_DIRECTORY);
ensureDirSync(renderSettingsDir);

screenRenderers.forEach((renderer) => {
const { tenant, ...screenRendererConfig } = renderer;
if (!renderer.prompt || !renderer.screen) {
log.error('Invalid screen renderer:', renderer);
return;
}
const fileName = `${renderer.prompt}_${renderer.screen}.json`;
const filePath = path.join(renderSettingsDir, fileName);

async function parseAndDump(context: YAMLContext): Promise<ParsedPrompts> {
log.info(`Writing ${filePath}`);

// Write individual file
writeFileSync(filePath, JSON.stringify(screenRendererConfig, null, 2));

// Find or create entry for this prompt in the screenRenderArray
let promptEntry = screenRenderArray.find((entry) => entry[renderer.prompt as string]);

if (!promptEntry) {
// If no entry exists for this prompt, create a new one
promptEntry = { [renderer.prompt as string]: {} };
screenRenderArray.push(promptEntry);
}

// Add screen to the prompt entry
promptEntry[renderer.prompt as string][
renderer.screen as string
] = `./prompts/${constants.PROMPTS_SCREEN_RENDER_DIRECTORY}/${fileName}`;
});

return screenRenderArray;
};

async function dump(context: YAMLContext): Promise<ParsedPrompts> {
const { prompts } = context.assets;

if (!prompts) return { prompts: null };

if (prompts.screenRenderers && prompts.screenRenderers.length > 0) {
prompts.screenRenderers = dumpScreenRenderers(context, prompts.screenRenderers);
}

return {
prompts,
};
}

const promptsHandler: YAMLHandler<ParsedPrompts> = {
parse: parseAndDump,
dump: parseAndDump,
parse,
dump,
};

export default promptsHandler;
Loading

0 comments on commit 66f0b01

Please sign in to comment.