Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading