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
11 changes: 7 additions & 4 deletions .github/workflows/run_tests.yml → .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: Run Tests
name: Continuous Integration

on:
pull_request:
types: [opened, reopened, synchronize]

jobs:
run_tests:
Continuous_Integration:
runs-on: ubuntu-latest

steps:
Expand All @@ -19,11 +19,14 @@ jobs:
with:
deno-version: latest

- name: Check formatting
run: |
deno fmt --check

- name: Run Tests
run: |
deno test \
--allow-read \
--allow-write \
--allow-env \
--allow-run \
--trace-leaks
--allow-run
33 changes: 21 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
This project helps decode Salesforce Flows by translating their raw XML
definition files into human-understandable UML diagrams. These visualizations
clarify the flow's structure and logic, making documentation and code review
significantly easier. It supports generating diagrams using PlantUML, Graphviz, and
Mermaid, and can even highlight changes between different versions of a flow by
processing Git diffs.
significantly easier. It supports generating diagrams using PlantUML, Graphviz,
and Mermaid, and can even highlight changes between different versions of a flow
by processing Git diffs.

Flow Lens is available on JSR, the JavaScript Registry. You can find the package at [jsr.io/@goog/flow-lens](https://jsr.io/@goog/flow-lens).
Flow Lens is available on JSR, the JavaScript Registry. You can find the package
at [jsr.io/@goog/flow-lens](https://jsr.io/@goog/flow-lens).

This is not an officially supported Google product. This project is not eligible
for the
Expand All @@ -21,7 +22,8 @@ for the
Graphviz, and Mermaid.
- **Handles Git diffs:** Can process changes between two Git commits,
highlighting added, modified, and deleted elements in the resulting diagram.
- **GitHub Action integration:** Automatically posts flow diagrams as comments on pull requests.
- **GitHub Action integration:** Automatically posts flow diagrams as comments
on pull requests.

## Usage

Expand All @@ -43,8 +45,11 @@ available:

Flow Lens supports two output modes:

1. **json mode (default):** Generates a JSON file containing the UML diagram(s) that can be used for further processing.
2. **github_action mode:** Automatically posts comments with flow diagrams on pull requests when used in a GitHub Actions workflow. When using this mode, you must specify `mermaid` as the diagram tool.
1. **json mode (default):** Generates a JSON file containing the UML diagram(s)
that can be used for further processing.
2. **github_action mode:** Automatically posts comments with flow diagrams on
pull requests when used in a GitHub Actions workflow. When using this mode,
you must specify `mermaid` as the diagram tool.

**Example using file path (json mode):**

Expand Down Expand Up @@ -80,7 +85,8 @@ deno run \

### Setting up a GitHub Action

You can set up a GitHub Action to automatically generate and post flow diagrams as comments on pull requests. Here's an example workflow configuration:
You can set up a GitHub Action to automatically generate and post flow diagrams
as comments on pull requests. Here's an example workflow configuration:

```yaml
name: Generate Flow Preview
Expand Down Expand Up @@ -122,13 +128,16 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

When using the GitHub Action mode, Flow Lens will automatically post a comment on the pull request with the old (if applicable) and new versions of the flow whenever a pull request is created or updated. This makes it easy to visualize flow changes directly in the pull request review process.
When using the GitHub Action mode, Flow Lens will automatically post a comment
on the pull request with the old (if applicable) and new versions of the flow
whenever a pull request is created or updated. This makes it easy to visualize
flow changes directly in the pull request review process.

## Output

When using the json mode, the output is a JSON file containing the generated UML diagram(s). The structure
will contain the file paths and their associated old (if applicable) and new UML
strings.
When using the json mode, the output is a JSON file containing the generated UML
diagram(s). The structure will contain the file paths and their associated old
(if applicable) and new UML strings.

```json
[
Expand Down
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@goog/flow-lens",
"version": "0.1.8",
"version": "0.1.9",
"license": "Apache",
"exports": "./src/main/main.ts",
"imports": {
Expand Down
34 changes: 19 additions & 15 deletions src/main/argument_processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,11 @@ export enum Mode {
*/
export const ERROR_MESSAGES = {
unsupportedDiagramTool: (diagramTool: string) =>
`Unsupported diagram tool: ${diagramTool}. Valid options are: ${Object.values(
DiagramTool
).join(", ")}`,
`Unsupported diagram tool: ${diagramTool}. Valid options are: ${
Object.values(
DiagramTool,
).join(", ")
}`,
filePathDoesNotExist: (filePath: string) =>
`filePath does not exist: ${filePath}`,
invalidOutputFileName: (outputFileName: string) =>
Expand All @@ -92,9 +94,11 @@ export const ERROR_MESSAGES = {
outputFileNameRequired: "outputFileName is required for JSON mode",
outputDirectoryRequired: "outputDirectory is required for JSON mode",
unsupportedMode: (mode: string) =>
`Unsupported mode: ${mode}. Valid options are: ${Object.values(Mode).join(
", "
)}`,
`Unsupported mode: ${mode}. Valid options are: ${
Object.values(Mode).join(
", ",
)
}`,
header: "The following errors were encountered:",
};

Expand Down Expand Up @@ -170,7 +174,7 @@ export class ArgumentProcessor {
!Object.values(DiagramTool).includes(lowerCaseDiagramTool as DiagramTool)
) {
this.errorsEncountered.push(
ERROR_MESSAGES.unsupportedDiagramTool(this.config.diagramTool)
ERROR_MESSAGES.unsupportedDiagramTool(this.config.diagramTool),
);
}
}
Expand All @@ -182,7 +186,7 @@ export class ArgumentProcessor {
!Object.values(Mode).includes(lowerCaseMode as Mode)
) {
this.errorsEncountered.push(
ERROR_MESSAGES.unsupportedMode(this.config.mode)
ERROR_MESSAGES.unsupportedMode(this.config.mode),
);
}
}
Expand All @@ -194,7 +198,7 @@ export class ArgumentProcessor {
for (const filePath of this.config.filePath) {
if (!fs.existsSync(filePath)) {
this.errorsEncountered.push(
ERROR_MESSAGES.filePathDoesNotExist(filePath)
ERROR_MESSAGES.filePathDoesNotExist(filePath),
);
}
}
Expand All @@ -208,7 +212,7 @@ export class ArgumentProcessor {
const regex = VALID_OUTPUT_FILE_NAME_REGEX;
if (!regex.test(this.config.outputFileName)) {
this.errorsEncountered.push(
ERROR_MESSAGES.invalidOutputFileName(this.config.outputFileName)
ERROR_MESSAGES.invalidOutputFileName(this.config.outputFileName),
);
}
}
Expand All @@ -220,7 +224,7 @@ export class ArgumentProcessor {
}
if (!fs.existsSync(this.config.outputDirectory)) {
this.errorsEncountered.push(
ERROR_MESSAGES.invalidOutputDirectory(this.config.outputDirectory)
ERROR_MESSAGES.invalidOutputDirectory(this.config.outputDirectory),
);
}
}
Expand All @@ -231,7 +235,7 @@ export class ArgumentProcessor {
!(this.config.gitDiffFromHash && this.config.gitDiffToHash)
) {
this.errorsEncountered.push(
ERROR_MESSAGES.filePathOrGitDiffFromAndToHashRequired
ERROR_MESSAGES.filePathOrGitDiffFromAndToHashRequired,
);
}
}
Expand All @@ -243,7 +247,7 @@ export class ArgumentProcessor {
(this.config.gitDiffFromHash || this.config.gitDiffToHash)
) {
this.errorsEncountered.push(
ERROR_MESSAGES.filePathAndGitDiffFromAndToHashMutuallyExclusive
ERROR_MESSAGES.filePathAndGitDiffFromAndToHashMutuallyExclusive,
);
}
}
Expand All @@ -254,15 +258,15 @@ export class ArgumentProcessor {
(this.config.gitDiffFromHash && !this.config.gitDiffToHash)
) {
this.errorsEncountered.push(
ERROR_MESSAGES.gitDiffFromAndToHashMustBeSpecifiedTogether
ERROR_MESSAGES.gitDiffFromAndToHashMustBeSpecifiedTogether,
);
}
}

private checkForErrors() {
if (this.errorsEncountered.length > 0) {
const errors: string[] = this.errorsEncountered.map(
(error) => `- ${error}`
(error) => `- ${error}`,
);
errors.unshift(ERROR_MESSAGES.header);
throw new Error(errors.join("\n"));
Expand Down
14 changes: 7 additions & 7 deletions src/main/flow_file_change_detector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const GIT_COMMANDS = {
getFileContent: (
filePath: string,
commitHash: string,
repo: string | undefined
repo: string | undefined,
) => `git ${repo ? `-C ${repo}` : ""} show ${commitHash}:${filePath}`,
};

Expand Down Expand Up @@ -82,11 +82,11 @@ export class FlowFileChangeDetector {
fromOrTo === "old"
? (Configuration.getInstance().gitDiffFromHash as string)
: (Configuration.getInstance().gitDiffToHash as string),
Configuration.getInstance().gitRepo
Configuration.getInstance().gitRepo,
);
} catch (error: unknown) {
throw new Error(
ERROR_MESSAGES.unableToGetFileContent(filePath, error as Error)
ERROR_MESSAGES.unableToGetFileContent(filePath, error as Error),
);
}
return fileContent.toString();
Expand Down Expand Up @@ -131,15 +131,15 @@ export class FlowFileChangeDetector {
GIT_COMMANDS.diff(
Configuration.getInstance().gitDiffFromHash!,
Configuration.getInstance().gitDiffToHash!,
Configuration.getInstance().gitRepo
)
Configuration.getInstance().gitRepo,
),
);
}

private executeGetFileContentCommand(
filePath: string,
commitHash: string,
repo: string | undefined
repo: string | undefined,
) {
return execSync(GIT_COMMANDS.getFileContent(filePath, commitHash, repo));
}
Expand All @@ -149,7 +149,7 @@ export class FlowFileChangeDetector {
.split(EOL)
.filter(
(filePath) =>
filePath && filePath.toLowerCase().endsWith(FLOW_FILE_EXTENSION)
filePath && filePath.toLowerCase().endsWith(FLOW_FILE_EXTENSION),
);
}
}
Loading