diff --git a/README.md b/README.md index 0cb0a218..80f44387 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,65 @@ -# **Vlocode**: Vlocity/Salesforce support libraries + -This is the monorepo root for all _@vlocode_ packages and the Vlocode VSCode extension. For information on the **Vlocode** VSCode extension [click here](packages/vscode-extension/README.md). +# Vlocode — Salesforce Industries / OmniStudio (Vlocity) tooling + +This is the monorepo for the [**Vlocode** VS Code extension](packages/vscode-extension/README.md) and a set of reusable `@vlocode/*` libraries that power it. Together they provide a fast, modern toolchain for Salesforce Industries, OmniStudio and standard Salesforce metadata development — without depending on the Vlocity Build Tools. + +For the VS Code extension and end-user documentation see [`packages/vscode-extension`](packages/vscode-extension/README.md). ## Packages -- [**@vlocode/util**](packages/util) - re-unable utility functions and classes -- [**@vlocode/vlocity-deploy**](packages/vlocity-deploy) - high performance Vlocity DataPack deployment library -- [**@vlocode/core**](packages/core) - IoC core and logging framework -- [**@vlocode/salesforce**](packages/salesforce) - Salesforce specific classes and functions -- [**Vlocode**](packages/vscode-extension) - Vlocode VSCode extension -- [**@vlocode/cli**](packages/cli) - Vlocode Standalone DataPack deployment CLI +| Package | Description | +| --- | --- | +| [**Vlocode**](packages/vscode-extension) | The VS Code extension for Salesforce Industries / OmniStudio and Salesforce metadata development. | +| [**@vlocode/cli**](packages/cli) | Stand-alone command-line Datapack deployment tool, ideal for CI/CD pipelines. | +| [**@vlocode/vlocity-deploy**](packages/vlocity-deploy) | High-performance Vlocity Datapack deployment library — the engine behind the extension and the CLI. | +| [**@vlocode/omniscript**](packages/omniscript) | Pure-JS OmniScript → LWC compiler and definition generator. | +| [**@vlocode/salesforce**](packages/salesforce) | Salesforce connectivity (REST, SOAP, Bulk, Metadata, Tooling) and high-level services. | +| [**@vlocode/apex**](packages/apex) | ANTLR4-based APEX & SOQL parser. | +| [**@vlocode/vlocity**](packages/vlocity) | Shared Vlocity domain types and matching-key logic. | +| [**@vlocode/sass**](packages/sass) | Out-of-process SASS/SCSS transpiler used to compile Vlocity UI Templates. | +| [**@vlocode/core**](packages/core) | IoC container, logging framework and filesystem abstraction. | +| [**@vlocode/util**](packages/util) | General-purpose utilities (iterables, caching, async, XML, decorators, ...). | +| [**@vlocode/vscode-webviews**](packages/vscode-webviews) | Angular webviews hosted by the VS Code extension. | ## Setup development environment -Vlocode uses `pnpm` as package manager and lerna release manager. To setup a developer environment for Vlocode you should always use the latest LTS version of node with corepack. VScode is the preferred IDE for developing and debugging. +Vlocode uses `pnpm` as package manager and `lerna-lite` for releases. Use the latest LTS version of Node with corepack. VS Code is the preferred IDE. -- check out this repository -- enable corepack and activate the `pnpm` package manager +- Check out this repository +- Enable corepack and activate the pinned `pnpm` version -```shell -$ corepack enable -$ corepack prepare $(node -p "require('./package.json').packageManager") --activate -``` + ```shell + corepack enable + corepack prepare $(node -p "require('./package.json').packageManager") --activate + ``` -- install all dependencies using pnpm, this will install all dependencies for packages in the monorepo +- Install all dependencies (this links the workspace packages): -```shell -pnpm install -``` + ```shell + pnpm install + ``` -- open the folder in VSCode and start coding; the `launch.json` and `tasks.json` that are part of this repository should allow you to run both the Vlocode CLI as well as debug the Vlocode extension without requiring any configuration +- Open the folder in VS Code. The committed `launch.json` and `tasks.json` let you run the CLI and debug the extension without further configuration. ## Tests -Each vlocode package comes with unit tests. To run all tests simply run `pnpm test` from the root folder which will run all package tests. P +Each package ships with Jest unit tests. From the repo root: -Vlocode uses jest as test runner and is pre-configured to generate a test converge report. +```shell +pnpm test +``` -**Note** you should run `pnpm build` if you are not running a watcher to ensure that all packages are transpiled and linked under _node_modules_. +Run `pnpm build` first if you are not running a watcher, so all packages are transpiled and linked under `node_modules`. -## Beta (Prerelease) Versions +## Beta (prerelease) versions -You can cut and publish a beta (preview) version of all packages and the VSCode extension using the new `release-beta` script. Beta builds: +You can cut and publish a beta of all packages and the extension with the `release-beta` script. Beta builds: -- use semantic version prerelease identifiers (e.g. `1.34.0-beta.0`) -- are published to GitHub Releases marked as *Pre-release* -- are uploaded to the VSCode Marketplace as *Preview* (using `vsce --pre-release`) -- can be iterated (`beta.1`, `beta.2`, ...); when you later publish a stable version (e.g. `1.34.0`) the preview flag is removed automatically by Marketplace +- use semantic-version prerelease identifiers (e.g. `1.34.0-beta.0`) +- are published to GitHub Releases marked as *Pre-release* +- are uploaded to the VS Code Marketplace as *Preview* (`vsce --pre-release`) +- can be iterated (`beta.1`, `beta.2`, ...) and are removed automatically when you later publish a stable version ### Creating a beta @@ -56,9 +69,9 @@ pnpm release-beta This runs `lerna version prerelease --preid beta` which: -1. Determines the next prerelease version for each changed package (conventional commits) -2. Updates `lerna.json` + individual `package.json` versions (e.g. `1.34.0-beta.0`) -3. Commits the changes and creates a git tag `v1.34.0-beta.0` +1. Determines the next prerelease version for each changed package (conventional commits) +2. Updates `lerna.json` and each `package.json` (e.g. `1.34.0-beta.0`) +3. Commits the changes and creates a git tag `v1.34.0-beta.0` Push the tag to trigger the GitHub Actions `Release` workflow: @@ -68,30 +81,30 @@ git push origin HEAD --follow-tags ### Publishing flow (CI) -The GitHub Actions release workflow detects prerelease versions (hyphen in the version) and automatically: +The release workflow detects prerelease versions (hyphen in the version) and automatically: -- passes `--pre-release` to the extension packaging & publish steps -- marks the GitHub Release as pre-release when the version contains a hyphen -- publishes all `@vlocode/*` npm packages with the `beta` dist-tag (so they don't overwrite `latest`) +- passes `--pre-release` to the extension packaging & publish steps +- marks the GitHub Release as pre-release +- publishes all `@vlocode/*` npm packages with the `beta` dist-tag (so they do not overwrite `latest`) ### Consuming beta npm packages -Install a beta version by either specifying the full version or using the `beta` tag: +Install a beta version by tag or explicit version: ```shell pnpm add @vlocode/core@beta -pnpm add @vlocode/util@1.34.0-beta.0 # explicit version example +pnpm add @vlocode/util@1.34.0-beta.0 ``` -To upgrade back to the stable channel later: +To go back to the stable channel later: ```shell pnpm up @vlocode/core@latest @vlocode/util@latest ``` -### Manually publishing the extension beta (optional) +### Manually publishing the extension beta -If you need to publish locally (e.g. testing credentials): +Only needed when testing credentials locally: ```shell pnpm publish-extension-beta @@ -104,8 +117,12 @@ This builds the extension and runs `vsce publish --pre-release` in the extension When ready for GA: ```shell -pnpm release-minor # or release-patch / manual lerna version command +pnpm release-minor # or release-patch / a manual lerna version command git push origin HEAD --follow-tags ``` -GitHub Actions will package without the prerelease flag and publish a normal release. +GitHub Actions then packages without the prerelease flag and publishes a normal release. + +## License + +[MIT](LICENSE) diff --git a/packages/apex/README.md b/packages/apex/README.md index 53063aad..22b7d84b 100644 --- a/packages/apex/README.md +++ b/packages/apex/README.md @@ -1,38 +1,24 @@ [![CI](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml/badge.svg)](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml) -[![GitHub top language](https://img.shields.io/github/languages/top/codeneos/vlocode.svg?logo=github)](https://github.com/Codeneos/vlocode) -[![Bugs](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/bugs.svg?color=lightgray&label=bugs&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) -[![Vulnerabilities](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/vulnerabilities.svg?label=vulnerabilities&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) -![NPM Version](https://img.shields.io/npm/v/%40vlocode%5Capex) +![NPM Version](https://img.shields.io/npm/v/%40vlocode%2Fapex) -# **@vlocode/apex** Salesforce APEX Language Parser +# @vlocode/apex — APEX & SOQL parser -Antlr4 based [APEX Parser](./src/grammar/ApexParser.ts) and [Grammar](./grammar/ApexParser.g4). This library uses [antlr4ng](https://github.com/mike-lischke/antlr4ng) as runtime library which is a port of the original antlr4 runtime library to TypeScript. - -The library exposes the APEX Lexer and APEX parser generated from the `.g4` grammar files allowing parsing of APEX source code using Visitor or Listener patterns. +An ANTLR4-based [APEX parser](./src/grammar/ApexParser.ts) and [grammar](./grammar/ApexParser.g4) for Node.js and the browser. Built on [`antlr4ng`](https://github.com/mike-lischke/antlr4ng) (the TypeScript port of the original ANTLR4 runtime), it exposes the APEX lexer and parser plus a small set of higher-level helpers built on top of them. ## Features -- Full APEX and SOQL grammar support -- Extract code structure from APEX source code -- Identify classes, fields, methods, properties and access modifiers -- Identify which classes are tested by which test classes - -## Example: Identifying test classes for a given class - -Below code demonstrates how to identify which classes are tested by which test classes. And prints the test classes for a given class name. +- Full APEX *and* SOQL grammar support +- Walk the parse tree with the standard ANTLR Visitor / Listener patterns +- Extract code structure (classes, fields, methods, properties, access modifiers) from raw source +- Identify which classes are exercised by which test classes — useful for delta-test selection in CI -```ts -import { TestIdentifier } from '@vlocode/apex'; +## Install -const testIdentifier = container.create(TestIdentifier); -await testIdentifier.loadApexClasses(['path/to/apex/classes']); -const testClasses = testIdentifier.getTestClasses('MyClass'); -console.log(testClasses); +```shell +npm install @vlocode/apex ``` -## Example: Extracting class information from APEX source code - -Below code demonstrates how to extract class information from an APEX source fragment and prints the class name, fields and methods as well as their access modifiers. +## Example: extract class structure from APEX source ```ts import { Parser } from '@vlocode/apex'; @@ -45,12 +31,12 @@ const sourceCode = `public class Person { get { return this.name; } } - public Integer getAge(Integer arg) { + public Integer getAge() { return this.age; } public Date getBirthDate() { - return Date.now(); + return Date.today(); } }`; @@ -72,18 +58,31 @@ for (const classInfo of struct.classes) { } ``` -Outputs the following: +Output: -```shell +```text Class Person Fields: 2 1) name (private) 2) age (private) Methods: 2 - 2) getAge (public) - 3) getBirthDate (public) + 1) getAge (public) + 2) getBirthDate (public) +``` + +## Example: find tests for a class + +```ts +import { TestIdentifier } from '@vlocode/apex'; +import { container } from '@vlocode/core'; + +const testIdentifier = container.create(TestIdentifier); +await testIdentifier.loadApexClasses(['path/to/apex/classes']); + +const testClasses = testIdentifier.getTestClasses('MyClass'); +console.log(testClasses); // ['MyClassTest', 'IntegrationTest', ...] ``` ## Credits -The grammar files in this library are based on the grammar files from the `apex-parser` NPM library originally maintained by Andrey Gavrikov. The original library is no longer maintained and the grammar files have been updated to work with the latest version of Salesforce and the antlr4ng runtime library. +The grammar files are adapted from the original `apex-parser` library by Andrey Gavrikov. That project is no longer maintained, so we updated the grammar to track newer APEX language features and the `antlr4ng` runtime. diff --git a/packages/cli/README.md b/packages/cli/README.md index e941b41e..9276dbc1 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -1,157 +1,232 @@ [![CI](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml/badge.svg)](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml) -[![GitHub top language](https://img.shields.io/github/languages/top/codeneos/vlocode.svg?logo=github)](https://github.com/Codeneos/vlocode) -[![Bugs](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/bugs.svg?color=lightgray&label=bugs&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) -[![Vulnerabilities](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/vulnerabilities.svg?label=vulnerabilities&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) +![NPM Version](https://img.shields.io/npm/v/%40vlocode%2Fcli) -# **vlocode-cli** a hyper fast :rocket: Vlocity Datapack deployment CLI +# vlocode-cli — a hyper-fast :rocket: Vlocity Datapack deployment CLI -Provides a fast Salesforce native tool for deploying **any** Vlocity Datapack JSON to any Salesforce org. +A stand-alone command-line tool for deploying, exporting, activating and converting **Vlocity / OmniStudio Datapacks** and related metadata against any Salesforce org. Built as a thin front-end around [`@vlocode/vlocity-deploy`](../vlocity-deploy), [`@vlocode/omniscript`](../omniscript) and [`@vlocode/salesforce`](../salesforce) — no dependency on the Vlocity Build Tools. -This CLI is built as showcase for the _[@vlocode/vlocity-deploy](https://www.npmjs.com/package/@vlocode/vlocity-deploy)_ NPM library, and does not use the Vlocity build tools NPM library.The CLI exposes a single command `deploy` which leverages _@vlocode/vlocity-deploy_. +## Why use it? -## Key differences with **[vlocityinc/vlocity_build](https://github.com/vlocityinc/vlocity_build)** and **Vlocity DX** +- :rocket: **10–20× faster** than the Vlocity Build Tools / DX on typical projects +- :computer: Dependency resolution and record conversion happen **client-side** +- :rainbow: **True delta** — compares source against the org and only deploys what actually changed +- :package: Single self-contained binary — trivial to drop into CI/CD +- :lock: Reproducible builds — all dependencies are bundled and pinned -- :rocket: Vlocode is **significantly faster** up to 10x-20x compared to Vlocity DX depending on the use case -- :computer: Vlocode does all the heavy lifting, dependency resolution, converting of datapacks **client side** -- :rainbow: Vlocode supports **true delta** check that is both fast and **reliable** as it can detect changes made in your org and restore them without relying on git +## What it does *not* do -## What does it **not** do... +- It does not generate FlexCard LWC components (planned) +- It is a CLI; for a UI use the [Vlocode VS Code extension](https://marketplace.visualstudio.com/items?itemName=curlybracket.vlocode) -- Vlocode deployment CLI is meant for deploying datapacks **not** for exporting/extracting them from an org -- Activate LWC OmniScripts and flex cards; for that use the client side LWC compiler of Vlocode (integration planed for future version) -- Provide you with a UI +## Install -## How to install +```shell +npm i -g @vlocode/cli +``` + +> If you intend to script against the deployment logic from your own Node project, depend on [`@vlocode/vlocity-deploy`](../vlocity-deploy) directly — this CLI is bundled and not meant to be imported as a library. -The Vlocode CLI is packaged as a dependency-free CLI with a bundled output build, making it _very_ fast to install. This also allows Vlocode CLI to be easily integrated in any CI/CD setup and helps guarantee consistent behavior as all dependencies (and their dependencies) are pinned. +## Quick start -> **Note** -> You should not depend on this package if you intend to use it as library, instead depend on **@vlocode/vlocity-deploy** which is the underlying library that implements all deployment logic. +Deploy a folder of Datapacks via interactive OAuth (production orgs need `--instance login.salesforce.com`): ```shell -$ npm i @vlocode/cli -g +vlocode deploy ./path/to/datapacks ``` -## Commands +Deploy using an existing SFDX alias or username: + +```shell +vlocode deploy ./path/to/datapacks -u my-sandbox +``` + +Export a single Datapack from the org: -List all commands available using the `--help` command. To get help on a specific command use the following command `vlocode --help`. +```shell +vlocode export 01t000000000001 -t Product2 -u my-sandbox +``` -### `vlocode deploy` +Re-activate every OmniScript whose type starts with `MACD/`: ```shell -Usage: vlocode deploy [options] +vlocode activate "MACD/*" -u my-sandbox +``` + +## Global options + +Every command supports the following options on top of its own: + +| Option | Default | Description | +| --- | --- | --- | +| `-v, --verbose` | `false` | Enable more detailed verbose logging. | +| `--debug` | `false` | Print the call stack when an unhandled error occurs. | +| `-h, --help` | — | Show help for the command. | + +Commands that talk to Salesforce additionally support the connection options below (any command marked *(Salesforce)*). + +| Option | Default | Description | +| --- | --- | --- | +| `-u, --user ` | — | Salesforce username or alias to authenticate with. When omitted, an interactive OAuth flow opens in the browser. | +| `-i, --instance ` | `test.salesforce.com` | Login host for the interactive OAuth flow. Use `login.salesforce.com` for production orgs. | +| `--record-session [file]` | — | Record the interaction with Salesforce to a session log so it can be replayed later. Conflicts with `--replay-session`. | +| `--replay-session ` | — | Replay a previously recorded session log instead of hitting Salesforce. Conflicts with `--record-session`. | + +## Commands + +Run `vlocode --help` for the full list, or `vlocode --help` for details. + +### `vlocode deploy` — deploy Datapacks *(Salesforce)* + +```text +Usage: vlocode deploy [options] Deploy datapacks to Salesforce Arguments: - folder path to a folder containing the datapacks to be deployed - -Options: - -v, --verbose enable verbose logging (default: false) - --debug print call stack when an unhandled error occurs (default: false) - -u, --user Salesforce username or alias of the org to deploy the datapacks to - -i, --instance the URL instance (default: "test.salesforce.com") - --purge-dependencies delete embedded dependencies with matching keys after the primary datapack record is - deployed. By default Vlocode will only delete child records that do not have a - matching key configuration, with this flag Vlocode will delete all child records that - have a lookup relationships to the primary datapack record. For example; when - deploying a Product2 datapack this flag will delete all child item records found in - the targer org with a lookup to the Product2 datapack that is deployed. (default: - false) - --lookup-failed lookup the Ids of records that failed to deploy but are dependencies for other parts - of the deployment (default: false) - --retry-count the number of times a record deployment is retried before failing it (default: 1) - --bulk-api use the Salesforce bulk API to update and insert records (default: false) - --delta check for changes between the source data packs and source org and only deploy the - datapacks that are changed (default: false) - --strict-dependencies enforce datapacks with dependencies on records inside other datapacks are fully - deployed. By default Vlocode determines deployment order based on record level - dependencies, this allows for more optimal chunking improving the overall speed of - the deployment. If you are running into deployment errors and think that Vlocode does - not follow the correct deployment order try enabling this setting. (default: false) - --skip-lwc skip LWC activation for LWC enabled OmniScripts (default: false) - --use-metadata-api deploy LWC components using the Metadata API (slower) instead of the Tooling API - (default: false) - --remote-script-activation use anonymous apex to activate OmniScripts.By default Vlocode will generate script - definitions locally which is faster and more reliable than remote activation. Enable - this when you experience issues or inconsistencies in scripts deployed through - Vlocode. (default: false) - -h, --help display help for command + paths one or more folders or files containing the datapacks to deploy ``` -### `vlocode activate` - -```shell +| Option | Default | Description | +| --- | --- | --- | +| `--purge-dependencies` | `false` | After deploying a primary record, also delete dependent child records linked through lookup relationships (in addition to those without a matching key). Example: when deploying a `Product2` datapack this removes child item records in the target org that look up to it. | +| `--lookup-failed` | `false` | If a dependency record fails to deploy, look up an existing record in the org that matches the lookup requirements. | +| `--allow-unresolved` | `false` | Continue deploying a datapack when a dependency cannot be resolved. The field carrying the missing dependency is set to `null`. Can cause inconsistent data — use only to unblock deployments. | +| `--retry-count ` | `1` | Number of times each record deployment is retried before being marked failed. | +| `--bulk-api` | `false` | Use the Salesforce Bulk API for inserts and updates. Significantly slower than the standard API; mostly useful to reduce callouts. | +| `--delta` | `false` | Compare the source datapacks against the org and only deploy the ones that changed. | +| `--strict-order` | `false` | Enforce strict Datapack-level ordering instead of record-level. Slower but improves compatibility when you hit ordering issues. | +| `--skip-lwc` | `false` | Skip LWC activation for LWC-enabled OmniScripts. | +| `--use-metadata-api` | `false` | Deploy LWC components via the Metadata API (slower) instead of the Tooling API. | +| `--remote-script-activation` | `false` | Activate OmniScripts via anonymous APEX on the server. By default Vlocode generates definitions locally, which is faster and more reliable. | +| `-y, --continue-on-error` | `false` | Continue deploying when one of the datapacks fails to load. By default any load/convert error aborts the deployment before changes are made. | + +### `vlocode activate` — activate OmniScripts *(Salesforce)* + +```text Usage: vlocode activate [options] [scriptFilter] Activate OmniScripts in Salesforce and deploy associated LWC components Arguments: - scriptFilter Salesforce ID /(/) filter of the scripts to activate. Supports - wildcard characters, i.e: "MACD/" to activate multiple scripts - -Options: - -v, --verbose enable verbose logging (default: false) - --debug print call stack when an unhandled error occurs (default: false) - -u, --user Salesforce username or alias of the org to deploy the datapacks to - -i, --instance Salesforce instance URL; for example: test.salesforce.com (default: "test.salesforce.com") - --parallel-activations determines the amount of parallel activations to run - --skip-lwc skip LWC activation for LWC enabled OmniScripts (default: false) - --use-metadata-api deploy LWC components using the Metadata API (slower) instead of the Tooling API (default: - false) - --remote-activation use anonymous apex to activate OmniScripts.By default Vlocode will generate script - definitions locally which is faster and more reliable than remote activation. Enable this - when you experience issues or inconsistencies in scripts deployed through Vlocode. (default: - false) - -h, --help display help for command + scriptFilter Salesforce Id, or a "/(/)" filter. Supports + wildcards (e.g. "MACD/*") to activate multiple scripts. ``` -## How to deploy using Vlocode CLI +| Option | Default | Description | +| --- | --- | --- | +| `--parallel-activations` | `4` | Number of activations to run in parallel. | +| `--skip-lwc` | `false` | Skip LWC activation for LWC-enabled OmniScripts. | +| `--use-metadata-api` | `false` | Deploy LWC components via the Metadata API instead of the (faster) Tooling API. | +| `--skip-reactivate-dependencies` | `false` | Skip re-activating parent scripts that embed the script being activated. By default, parents that embed a reusable script are re-activated automatically. | +| `--remote-activation` | `false` | Activate OmniScripts via anonymous APEX. By default Vlocode generates definitions locally. | +| `--debug-activation` | `false` | Save the generated script definitions as a JSON file. Useful for comparing local vs. remote activation output. | -You can use any existing SFDX credentials or OAuth2 to login into tge target org. If you do not provided an SFDX username or alias you will automatically get an OAuth popup. +### `vlocode export` — export Datapacks *(Salesforce)* -To deploy and login using OAuth2 (for production orgs pass `--instance login.salesforce.com`) use the following basic command, where the last argument is the path (relative or full) to the folder containing the \*\_DataPack.json files to deploy. Vlocode will recursively scan the specified folder and deploy all datapacks found. +```text +Usage: vlocode export [options] [ids...] -```shell -vlocode deploy ./path-to-datapack-json-files +Export an object as datapack from Salesforce + +Arguments: + ids one or more Salesforce record IDs to export ``` -To use an existing SFDX credential or alias use: +| Option | Default | Description | +| --- | --- | --- | +| `-d, --export-definitions ` | — | YAML or JSON file with export definitions describing how objects expand into datapacks. | +| `-f, --file ` | — | YAML export file with one or more datapack queries. Conflicts with `--query`. | +| `-e, --expand` | `false` | After exporting, expand each datapack into separate files following the export definitions. | +| `-q, --query ` | — | SOQL query to use instead of record IDs. Conflicts with `--file`. | +| `-t, --datapack-type ` | — | Datapack type when exporting by ID or a single query. | +| `--folder ` | `./` | Folder where exported datapacks are written. | +| `--depth ` | — | Dependency export depth. Use `-1` to include all transitive dependencies. | -```shell -vlocode deploy ./path-to-datapack-json-files -u +### `vlocode bulk-export` — Bulk API v2 data export *(Salesforce)* + +```text +Usage: vlocode bulk-export [options] [sobject] + +Export data from Salesforce using the Bulk API v2 and output as NDJSON + +Arguments: + sobject SObject name to query (used only when neither --query nor --file is given) ``` -## FAQ +| Option | Default | Description | +| --- | --- | --- | +| `-o, --output ` | **required** | Path to the output NDJSON file. | +| `-q, --query ` | — | SOQL query string to execute. Conflicts with `--file`. | +| `-f, --file ` | — | Path to a file containing a SOQL query. Conflicts with `--query`. | +| `-l, --limit ` | — | Limit the number of records to export. Only applies when an SObject name is provided. | +| `--include-deleted` | `false` | Include deleted records in the query (uses `queryAll`). | +| `--chunk-size ` | `50000` | Number of records to retrieve per API call. | + +### `vlocode convert` — convert legacy Datapacks to OmniStudio *(Salesforce)* + +```text +Usage: vlocode convert [options] -**Q: Does vlocode deploy the LWC enabled OmniScripts?** +Convert Managed runtime OmniScript datapacks to native OmniProcess datapacks -**A:** Yes, vlocode will deploy the OmniScript and compile the LWC component and deploy it using either the Metadata API or the Tooling API. By default the tooling API is used as it can run in parallel to an ongoing metadata deployment. +Arguments: + paths one or more folders or files containing the datapacks to convert +``` + +Converts Vlocity (`vlocity_cmt__`) OmniScript datapacks into native OmniStudio (`OmniProcess`) datapacks. Uses only the global and Salesforce connection options listed above. -**Q: Does vlocode deploy custom datapack properties that are not part of the standard datapack definition?** +### `vlocode build-export-definitions` — generate export YAML *(Salesforce)* -**A:** Yes, vlocode will load the datapack and match the fields in the datapack against the fields available in the target org. Matching fields are deployed, for any field that is specified in the datapack but not available an error is generated which can be reviewed at the end of the deployment. +```text +Usage: vlocode build-export-definitions [options] -**Q: Vlocode does not delete Product Child Item's (PCI) that I have removed from the datapack, why is that?** +Generate DatapackExportDefinition YAML from DRMapItem migration records +``` + +| Option | Default | Description | +| --- | --- | --- | +| `-e, --expand-definition ` | — | Optional path to a `DatapacksExpandDefinition` YAML file that controls how datapacks are split into files. | +| `-x, --expanded` | `false` | Write one YAML file per datapack definition instead of a single combined file. | +| `-o, --output ` | `./export-definitions.yaml` | Output YAML path used when `--expanded` is *not* set. | +| `-d, --output-dir ` | `./datapack-export-definitions` | Output directory used when `--expanded` is set. | -**A:** Vlocode will is designed to be safe to run on production orgs and does not delete records unless explicitly requested. When removing child items from the product hierarchy it is recommended to set the state to disabled instead of deleting the PCI as deleting the PCI will have side effects on cached content and Assets already created based on the old definition. +### `vlocode impacted-tests` — find impacted APEX tests -For none production orgs you can enable the `--purge-dependencies` option which will first delete all embedded records and only then deploy the new ones. +```text +Usage: vlocode impacted-tests [options] -**Q: Should I prefer the `--bulk-api` option for production deployments?** +Find impacted unit tests for a given set of APEX classes -**A:** No, the performance of the bulk API is worse as it is dependent on the available resources on Salesforce and runs at a lower priority compared to regular database API operations. You will see inconsistent performance when using the `--bulk-api` and should only prefer it if you want to reduce API usage consumption when deploying. +Arguments: + folders one or more folders containing the APEX classes and triggers to parse +``` + +| Option | Default | Description | +| --- | --- | --- | +| `--classes ` | — | Classes to look up impacted tests for. If omitted, the impact map is built for every class found. | +| `--output ` | `impactedTests.json` | Path to the JSON file containing the impacted-tests map. | + +This command parses APEX source locally and does not need a Salesforce connection. + +## FAQ -**Q: When I actictae my OmniScript from the UI it looks different then the one deployed by Vlocode** +**Q: Does Vlocode deploy LWC-enabled OmniScripts?** +A: Yes. Vlocode deploys the OmniScript, compiles the LWC locally and deploys it via the Tooling API (default) or the Metadata API. The Tooling API can run in parallel to an ongoing metadata deployment. -**A:** By default vlocode-cli will use a feature of the Vlocode deployment library called _local script definition generation_. This means that script definitions are generated by Vlocode instead of running a Vlocity remote APEX function. Although this feature has been extensively tested there is a possibility of mismatches which can either be due to bugs in the local script definition generation feature or in the APEX code running on Salesforce. +**Q: Does Vlocode honour custom Datapack fields that are not part of the standard definition?** +A: Yes. Vlocode loads the Datapack, matches its fields against the SObject schema in the target org, deploys the ones that exist, and reports errors for the ones that do not. -if you encounter such discrepancy you can disable _local script definition generation_ by passing `--remote-script-activation` to the deployment. Also raise a bug on Github so that the _local script definition generation_ can be updated to handle your specific use case. +**Q: Vlocode does not delete Product Child Items (PCI) that I removed from the Datapack — why?** +A: Vlocode is safe-by-default and does not delete records unless asked to. The recommended approach for the product hierarchy is to **disable** a PCI rather than delete it, because deletions have cascading effects on cached content and existing Assets. For non-production orgs you can pass `--purge-dependencies` to delete embedded records before re-deploying. -**Q: Does vlocode compile FlexCards into LWC components?** +**Q: Should I prefer `--bulk-api` for production deployments?** +A: No. The Bulk API runs at lower priority and depends on available org resources, so its performance is more variable than the standard Collections API. Use it to save API limits, not to go faster. -**A:** No, at this moment Vlocode does not generate the LWC components for Flexcards. This is planned but due to the complexity and effort involved in porting the flex-card activation code to Javascript it will a bit more time for this to become available in vlocode as stable feature. +**Q: When I activate my OmniScript from the UI it looks different from the one deployed by Vlocode — why?** +A: By default Vlocode generates the script definition locally instead of calling Vlocity's remote APEX activation. The implementation is well-tested but the OmniStudio managed package keeps evolving, so mismatches are possible. If you hit one, fall back to `--remote-script-activation` and please open a bug so we can update the local generator. -**Q: We want to use Vlocode to improve our deployment, can you help us?** +**Q: Does Vlocode compile FlexCards into LWC components?** +A: Not yet. The activation logic is significantly more involved than OmniScript and is still being ported. The VS Code extension can activate FlexCards via the standard Vlocity flow in the meantime. -**A:** Yes, support for project implementations can be provided on request. +**Q: We want help adopting Vlocode on a project — can you support us?** +A: Yes, support engagements are available on request. diff --git a/packages/core/README.md b/packages/core/README.md new file mode 100644 index 00000000..3a6e171b --- /dev/null +++ b/packages/core/README.md @@ -0,0 +1,57 @@ +[![CI](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml/badge.svg)](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml) +![NPM Version](https://img.shields.io/npm/v/%40vlocode%2Fcore) + +# @vlocode/core — IoC, logging and filesystem core + +The foundation that the rest of the `@vlocode/*` libraries (and the Vlocode VS Code extension) are built on. It bundles a small dependency-injection container, a configurable logging framework and a minimal filesystem abstraction that works both inside VS Code and in plain Node.js. + +`@vlocode/core` has a single peer dependency on the matching version of [`@vlocode/util`](../util). + +## Features + +- **IoC container** — constructor injection with `@injectable` / `@inject` decorators, scoped child containers, factory and singleton bindings +- **Logging** — structured log entries, level filtering, multiple writers (console, VS Code output channel, in-memory, file) and per-category log levels +- **Filesystem abstraction** — one interface, Node and VS Code implementations, so the same code runs in both worlds +- **Deferred work queue** — debounced/coalesced background work helper + +## Install + +```shell +npm install @vlocode/core @vlocode/util +``` + +## Example: dependency injection + +```ts +import { container, injectable, inject } from '@vlocode/core'; + +@injectable() +class TimeService { + now() { return new Date(); } +} + +@injectable() +class Greeter { + constructor(@inject(TimeService) private readonly time: TimeService) {} + + greet(name: string) { + return `Hello ${name} (it is ${this.time.now().toISOString()})`; + } +} + +const greeter = container.get(Greeter); +console.log(greeter.greet('world')); +``` + +## Example: logging + +```ts +import { LogManager, LogLevel, ConsoleWriter } from '@vlocode/core'; + +LogManager.registerWriter(new ConsoleWriter()); +LogManager.setGlobalLogLevel(LogLevel.info); + +const log = LogManager.get('my-app'); +log.info('Started'); +log.warn('Heads up: %s', 'something looks off'); +``` diff --git a/packages/omniscript/README.md b/packages/omniscript/README.md index f0d6dea6..15afe8cd 100644 --- a/packages/omniscript/README.md +++ b/packages/omniscript/README.md @@ -1,8 +1,54 @@ [![CI](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml/badge.svg)](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml) -[![GitHub top language](https://img.shields.io/github/languages/top/codeneos/vlocode.svg?logo=github)](https://github.com/Codeneos/vlocode) -[![Bugs](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/bugs.svg?color=lightgray&label=bugs&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) -[![Vulnerabilities](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/vulnerabilities.svg?label=vulnerabilities&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) +![NPM Version](https://img.shields.io/npm/v/%40vlocode%2Fomniscript) -# **@vlocode/omniscript** Vlocode OmniScript Library +# @vlocode/omniscript — fast OmniScript → LWC compiler -A fast pure-JS library for generating **any** Vlocity OmniScript definitions and LWC components from a set of OmniScript JSON files. This library is built from scratch to provide a fast and reliable way to generate OmniScript definitions and LWC components not having to rely on APEX REST APIs and DataRaptors. +A pure-JavaScript library that generates **Vlocity / OmniStudio OmniScript definitions and Lightning Web Components** straight from the OmniScript JSON source files. No APEX REST calls, no DataRaptors, no round-trip to the org. + +This is what powers the `OmniScript: Generate LWC` and `OmniScript: (Re-)Activate` commands in the [Vlocode VS Code extension](https://marketplace.visualstudio.com/items?itemName=curlybracket.vlocode) and the OmniScript activation step in [`@vlocode/cli`](../cli). + +## Features + +- **Local script definition generation** — produce the activated `OmniScript` JSON locally, no anonymous APEX needed +- **LWC component generation** — emit a ready-to-deploy LWC bundle (`.html`, `.js`, `.js-meta.xml`, `.css`) for any OmniScript +- **Bulk activation** — activate many OmniScripts in parallel, dramatically faster than the standard activation flow +- **Namespace-aware** — works against both Vlocity (`vlocity_cmt__`) and standard OmniStudio (`omnistudio__`) orgs +- **No managed-package APEX dependency** — avoids SOQL governor limit failures on large scripts + +## Install + +```shell +npm install @vlocode/omniscript @vlocode/salesforce @vlocode/core +``` + +## Example: generate an LWC from an OmniScript + +```ts +import { OmniScriptLwcCompiler } from '@vlocode/omniscript'; +import { container } from '@vlocode/core'; + +const compiler = container.get(OmniScriptLwcCompiler); +const bundle = await compiler.compile({ + type: 'Account', + subType: 'Onboarding', + language: 'English', + definition, // OmniScript definition JSON +}); + +for (const file of bundle.files) { + console.log(file.path, file.content.length); +} +``` + +## Example: activate scripts in a connected org + +```ts +import { OmniScriptActivator } from '@vlocode/omniscript'; + +const activator = container.get(OmniScriptActivator); +await activator.activate({ + connection, // @vlocode/salesforce connection + filter: 'Account/Onboarding/*', // type/subType/language wildcard + parallel: 4, +}); +``` diff --git a/packages/salesforce/README.md b/packages/salesforce/README.md new file mode 100644 index 00000000..f81c1a32 --- /dev/null +++ b/packages/salesforce/README.md @@ -0,0 +1,75 @@ +[![CI](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml/badge.svg)](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml) +![NPM Version](https://img.shields.io/npm/v/%40vlocode%2Fsalesforce) + +# @vlocode/salesforce — high-level Salesforce client + +A batteries-included Salesforce client library. It wraps JSForce and the Salesforce SOAP / REST / Bulk / Metadata / Tooling APIs in services with sensible defaults, retry behaviour, batching and a consistent query API. + +This is the library that powers the Vlocode VS Code extension and the [`@vlocode/cli`](../cli) deployment tool. It is fully usable on its own. + +## Features + +- **Connections** — build connections from SFDX usernames or aliases, refresh tokens automatically +- **Query service** — SOQL with caching, automatic chunking and typed result mapping +- **Query builder** — compose SOQL programmatically with parent / child relationship traversal +- **Metadata deploy & retrieve** — SFDX *and* classic Metadata API formats, with packaging helpers +- **Tooling API** — LWC, Aura and APEX deployment via the (fast) Tooling API +- **Bulk API** — insert/update/upsert/delete with progress callbacks +- **Record batch** — transparently splits large DML operations into Composite/Collections API chunks +- **Profile service** — add or remove field / object / APEX class permissions across multiple profiles +- **Debug logs** — stream, fetch and clear Apex Debug Logs, manage TraceFlags +- **Anonymous APEX** — execute snippets and retrieve the resulting log in one call +- **Schema service** — cached SObject and field describes, namespace-aware + +## Install + +```shell +npm install @vlocode/salesforce @vlocode/core @vlocode/util +``` + +## Example: query an org by SFDX alias + +```ts +import { SalesforceService } from '@vlocode/salesforce'; +import { container } from '@vlocode/core'; + +const sf = container.get(SalesforceService); +await sf.connect({ sfdxUsername: 'my-scratch-alias' }); + +const accounts = await sf.query<{ Id: string; Name: string }>( + 'SELECT Id, Name FROM Account WHERE Industry = :industry LIMIT 10', + { industry: 'Technology' } +); +``` + +## Example: execute anonymous APEX + +```ts +import { SalesforceService } from '@vlocode/salesforce'; + +const result = await salesforce.executeAnonymous(` + List accs = [SELECT Id, Name FROM Account LIMIT 5]; + for (Account a : accs) System.debug(a.Name); +`); + +console.log(result.success, result.log); +``` + +## Example: deploy metadata + +```ts +import { SalesforceDeployService, PackageBuilder } from '@vlocode/salesforce'; + +const pkg = new PackageBuilder({ apiVersion: '60.0' }) + .addFiles(['./force-app/main/default/classes/MyClass.cls']) + .build(); + +const deploy = container.get(SalesforceDeployService); +const result = await deploy.deploy(pkg, { connection }); + +if (!result.success) { + for (const error of result.details.componentFailures ?? []) { + console.error(`${error.fileName}: ${error.problem}`); + } +} +``` diff --git a/packages/sass/README.md b/packages/sass/README.md index e0707bba..00842107 100644 --- a/packages/sass/README.md +++ b/packages/sass/README.md @@ -1,18 +1,32 @@ [![CI](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml/badge.svg)](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml) -[![GitHub top language](https://img.shields.io/github/languages/top/codeneos/vlocode.svg?logo=github)](https://github.com/Codeneos/vlocode) -[![Bugs](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/bugs.svg?color=lightgray&label=bugs&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) -[![Vulnerabilities](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/vulnerabilities.svg?label=vulnerabilities&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) -![NPM Version](https://img.shields.io/npm/v/%40vlocode%5Capex) +![NPM Version](https://img.shields.io/npm/v/%40vlocode%2Fsass) -# **@vlocode/sass** Salesforce SESS/SCSS Transpiler +# @vlocode/sass — SCSS transpiler for Vlocity UI Templates -Pure NodeJS based SASS/SCSS transpiler for Vlocity UI Templates SESS/SCSS files. Uses the [sass](https://www.npmjs.com/package/sass) NPM package to transpile SESS/SCSS files to CSS. +A small Node.js wrapper around [`sass`](https://www.npmjs.com/package/sass) that transpiles the `.sess` / `.scss` files shipped with Vlocity UI Templates into CSS, out-of-process so the host application stays responsive. -Used by the [Vlocode for VS Code](https://marketplace.visualstudio.com/items?itemName=curlybracket.vlocode) extension to transpile SESS/SCSS files to CSS when deploying Vlocity UI Templates to Salesforce. +Used by the [Vlocode VS Code extension](https://marketplace.visualstudio.com/items?itemName=curlybracket.vlocode) to compile UI Template styles when deploying to Salesforce. ## Features -- Transpile SESS/SCSS files to CSS -- Supports SESS/SCSS imports -- Supports SESS/SCSS variables -- Running transpilation in a separate process to avoid blocking the main thread +- Transpile `.sess` / `.scss` files to CSS +- Resolves `@import` and `@use` dependencies +- Variables, mixins and the rest of the standard Dart-Sass feature set +- Runs the compilation in a worker process so it never blocks the main thread + +## Install + +```shell +npm install @vlocode/sass +``` + +## Example + +```ts +import { SassCompiler } from '@vlocode/sass'; + +const compiler = new SassCompiler(); +const css = await compiler.compileFile('./templates/MyTemplate/style.scss'); + +console.log(css); +``` diff --git a/packages/util/README.md b/packages/util/README.md new file mode 100644 index 00000000..8e6c6936 --- /dev/null +++ b/packages/util/README.md @@ -0,0 +1,62 @@ +[![CI](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml/badge.svg)](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml) +![NPM Version](https://img.shields.io/npm/v/%40vlocode%2Futil) + +# @vlocode/util — small, sharp utilities + +A toolbox of focused helpers that the rest of the Vlocode libraries lean on. Nothing here is Vlocity- or Salesforce-specific in any deep way — if you find a function here useful, take it. + +## What's inside + +- **Iterables / collections** — lazy `map` / `filter` / `groupBy` / `chunk` / `unique` and friends that work on any `Iterable` +- **Async helpers** — `Deferred`, async event emitter, cancellation tokens, debounce/throttle, retry +- **Caching** — method/function `@cache` decorator, `TimedMap` with TTL eviction, transactional map +- **String / object** — deep merge, deep equal, format, case conversion +- **XML** — small, fast XML parser/serializer for Salesforce metadata files +- **Filesystem** — recursive `find`, glob match, atomic write helpers +- **Salesforce helpers** — ID normalization (15 ↔ 18), namespace stripping, SObject helpers +- **SFDX helpers** — resolve usernames and build authenticated connections from your existing SFDX auth +- **Decorators** — `@singleton`, `@cache`, `@once`, `@wrap`, validators +- **Reflection** — lightweight type metadata utilities used by the `@vlocode/core` container + +## Install + +```shell +npm install @vlocode/util +``` + +## Example: cached method + +```ts +import { cache } from '@vlocode/util'; + +class Pricing { + @cache({ ttl: 60_000 }) + async getQuote(productId: string) { + return fetch(`/api/quote/${productId}`).then(r => r.json()); + } +} +``` + +## Example: iterable helpers + +```ts +import { Iterable } from '@vlocode/util'; + +const totalsByCategory = Iterable.from(orders) + .filter(o => o.status === 'paid') + .groupBy(o => o.category) + .map(([category, items]) => ({ + category, + total: items.reduce((s, i) => s + i.amount, 0), + })) + .toArray(); +``` + +## Example: build a connection from SFDX + +```ts +import { sfdx } from '@vlocode/util'; + +const connection = await sfdx.getConnection('my-scratch-alias'); +const result = await connection.query('SELECT Id, Name FROM Account LIMIT 5'); +``` diff --git a/packages/vlocity-deploy/README.md b/packages/vlocity-deploy/README.md index f9051755..a83ea9d6 100644 --- a/packages/vlocity-deploy/README.md +++ b/packages/vlocity-deploy/README.md @@ -1,132 +1,119 @@ [![CI](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml/badge.svg)](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml) -[![GitHub top language](https://img.shields.io/github/languages/top/codeneos/vlocode.svg?logo=github)](https://github.com/Codeneos/vlocode) -[![Bugs](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/bugs.svg?color=lightgray&label=bugs&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) -[![Vulnerabilities](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/vulnerabilities.svg?label=vulnerabilities&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) +![NPM Version](https://img.shields.io/npm/v/%40vlocode%2Fvlocity-deploy) -# **@vlocode/vlocity-deploy** a hyper fast :rocket: Vlocity Datapack deployment Library +# @vlocode/vlocity-deploy — a hyper-fast :rocket: Vlocity Datapack deployment library -A fast pure-JS library for deploying **any** Vlocity Datapack to Salesforce. +A pure-JavaScript library that deploys **any** Vlocity / OmniStudio Datapack to Salesforce. Built from scratch to be fast and reliable, with **no dependency on Vlocity APEX REST endpoints, DataRaptors or the Vlocity Build Tools**. -This library is built from scratch to provide a fast and reliable way to deploy Datapack definitions to Salesforce not having to rely on APEX REST APIs and DataRaptors. +This library is the engine behind the [Vlocode VS Code extension](https://marketplace.visualstudio.com/items?itemName=curlybracket.vlocode) and the [`@vlocode/cli`](../cli) command-line tool. -## Key differences with **[vlocityinc/vlocity_build](https://github.com/vlocityinc/vlocity_build)** and **Vlocity DX** +## Why it's different -- :rocket: Vlocode is **significantly faster** up to 10x-20x compared to Vlocity DX depending on the use case -- :computer: Vlocode does all the heavy lifting, dependency resolution, converting of datapacks **client side** -- :rainbow: Vlocode supports **true delta** check that is both fast and **reliable** as it can detect changes made in your org and restore them without relying on git -- :muscle: Vlocode battle tested on production deployments and covered by **Jest unit tests** -- :heart: Vlocode is fully written in **TypeScript** with extensive code-level documentation -- :pencil2: Vlocode deployment logic can easily be **extended** using Spec classes and Hook functions -- :page_with_curl:: Vlocode is [fully documented](https://vlocode.curlybracket.nl/modules/_vlocode_vlocity_deploy.html) +- :rocket: **10–20× faster** than Vlocity Build Tools / DX on typical projects +- :computer: Dependency resolution and Datapack → record conversion happen **client-side** +- :rainbow: **True delta** — reliably detects org-side changes without relying on git history +- :muscle: Battle-tested on production deployments, covered by Jest unit tests +- :heart: Fully written in **TypeScript** with extensive in-code documentation +- :pencil2: **Extensible** — hook into every stage of the deployment with custom specs +- :page_with_curl: [Fully documented API](https://vlocode.curlybracket.nl/modules/_vlocode_vlocity_deploy.html) -### Also... +Also: -- Vlocode does client-side OmniScript to LWC compilation and deployment -- Vlocode does client-side OmniScript Activation avoiding SOQL limit exceptions when activating big scripts +- Client-side OmniScript → LWC compilation and deployment +- Client-side OmniScript activation that avoids SOQL governor limits for large scripts -## What does it **not** do... +## What it does *not* do -- Vlocode vlocity-deploy library is meant for deploying datapacks **not** for exporting/extracting them from an org -- Activation of flex cards -- Provide you with a (fancy) UI +- It deploys; it does not export/retrieve Datapacks +- It does not yet activate FlexCards +- It is a library — for a UI use the [VS Code extension](https://marketplace.visualstudio.com/items?itemName=curlybracket.vlocode), for a CLI use [`@vlocode/cli`](../cli) -# Why is Vlocode faster? +## Why is Vlocode faster? -Vlocode is significantly faster then the regular Vlocity/OmniStudio Datapack deployment because it takes a fundamental different approach to deployment of Datapacks. Instead of relying on server side Apex REST APIs and DataRaptors Vlocode does all the heavy lifting client side. This means that Vlocode does not need to make any round trips to the server to resolve dependencies that it just deployed, convert Datapacks to Salesforce records and deploy them to Salesforce. +Vlocode takes a fundamentally different approach to Datapack deployment. Instead of leaning on server-side APEX REST endpoints and DataRaptors, it does the heavy lifting locally. That removes a *lot* of round-trips: dependency resolution, Datapack-to-record conversion and matching-key lookups all happen in the client. -Especially when deploying larger projects with many dependencies Vlocode can be up to 10x-20x faster then the regular Vlocity/OmniStudio deployment tools. The following table shows the results of a benchmark test that was run on a project with 1000+ datapacks and 100+ dependencies. +On large projects with many cross-Datapack dependencies the difference is dramatic. Benchmark from a real project with 1000+ datapacks and 100+ dependencies: | Tool | Time | | ------------------ | ------- | | Vlocode | 7m 54s | | Vlocity/OmniStudio | 92m 12s | -# How does it work? +## How it works -1. First Vlocode converts all the datapacks to Salesforce records the process takes about 5 seconds per 1000 datapacks and depends primarily on the performance of the hardware on which Vlocode is running. Vlocode will also validate the records and report any errors that it encounters during the conversion process such as none-existing fields or invalid field values. +1. **Convert** — all Datapacks are converted into Salesforce records (~5s per 1000 datapacks). Vlocode validates fields against the target org schema and reports unknown fields or invalid values up-front. +2. **Resolve dependencies** — Vlocode builds a virtual dependency graph at the **record** level (not the Datapack level), which lets it deploy in the optimal order and chunk aggressively (~1s per 1000 records). For Datapacks that need special handling (e.g. OmniScripts) a *deployment spec registry* lets you hook the process. +3. **Deploy** — records are pushed via the Salesforce Collections API (default) or the Bulk API. After insert, Vlocode validates `*GlobalKey__c` field integrity since these are overwritten by Vlocity triggers; mismatches are corrected via a trigger-disabled update. +4. **Activate** — OmniScripts and LWCs are activated in parallel via the Tooling API. -2. The second step in the deployment process is building a virtual dependency graph. Vlocode will determine which record to deploy first and which records need to wait for their dependencies to be deployed. It considered all to be deployed records individually outside of their datapack context, this allows Vlocode to deploy records in the most optimal order. The dependency resolution process takes about 1 second per 1000 records. +## Install - > Some datapacks require special handling, for example OmniScripts. To allow for this Vlocode uses a deployment spec/hook registry that allows to registering custom functions for specific datapacks. Specs can change the datapack prior to deployment, run pre- and post-deployment activation logic and can also be used to manipulate the record data of individual records before they are deployed. Vlocode comes with a set of default specs for standard datapacks such as OmniScripts and Product2 but custom specs can be registered to extend the deployment process. - -3. The third step in the deployment process is deploying the records to Salesforce. Vlocode uses the Salesforce Collections API or Bulk API to deploy records directly to Salesforce. After a record is deployed Vlocode validates field integrity of `\*GlobalKey\_\_c`` fields as these are overwritten by Vlocity when a new record is inserted. If these do not matching an extra update is done with all triggers disabled to correct the field value. - -4. The final step in the deployment process is activating the deployed records. Vlocode uses the Salesforce Tooling API to activate OmniScripts and LWCs. The activation process is done in parallel and is significantly faster then the regular Vlocity/OmniStudio activation process. - -# How to use - -The Vlocode vlocity-deploy is a library that you can use inside your own deployment toolkit. It depends on other vlocode packages for communication with Salesforce and for providing utility functions. You shouldn't need to depend on on any other @vlocode libraries to use `@vlocode/vlocity-deploy` but if you do it is advisable to keep all @vlocode packages aligned to each other to avoid loading multiple version of each library. - -A convenience function is exported from `@vlocode/vlocity-deploy` which starts a new deployment. In order to connect to Salesforce the deploy functions needs either an SFDX username -or- an JSForce compatible connection object. - -You can also change how `@vlocode/vlocity-deploy` logs messages; by default informational messages are printed through the `console` interface. - -| Option | Description | -| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `connection` | JSForce compatible connection object; vlocode will not directly use the connection passed if it wasn't created through the `@Vlocode/salesforce` library. In such cases Vlocode will create a new `vlocode.salesforceConnection`. This is required to work around several bugs in `jsforce` which would otherwise break the deployment. | -| `sfdxUser` | When an SFDX user name is passed Vlocode will create a new SFDX connection (`vlocode.salesforceConnection`) and use that for interacting with Salesforce. | -| `logger` | Custom logging interface to which the deployment writes all messages, see **Use a Custom logger** to read how to implement a custom logger. | +```shell +npm install @vlocode/vlocity-deploy @vlocode/salesforce @vlocode/core +``` -The deploy function returns a [`DatapackDeployment`](https://vlocode.curlybracket.nl/classes/_vlocode_vlocity_deploy.DatapackDeployment.html) object which contains extensive information about the deployment including the deployed records and warnings/error messages (see `getMessages()` in `DatapackDeployment`). +## Quick start -## Example snippet (JS) +`deploy()` takes either an SFDX username/alias or a JSForce-compatible connection. ```js import { deploy } from '@vlocode/vlocity-deploy'; -import { connection } from 'jsforce'; const deployment = await deploy('./vlocity/datapacks/', { - connection: new connection(...) /* JS-Force connection */ - sfdxUser: 'user@example.com.testOrg' /* SFDX User Name */ - // logger: { ... } + sfdxUser: 'user@example.com.testOrg', + // or: connection: existingJsForceConnection, + // logger: { write(entry) { console.log(entry.message); } }, }); for (const message of deployment.getMessages()) { - // Each message also contains a `record` object that caused the message - console.log(`${type}: ${message}`); + console.log(`${message.type}: ${message.message}`); } ``` -## Vlocode deploy options - -Below the list of options that can be passed to the `deploy` function - -| Option | Default | Description | -| ----------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `disableTriggers` | `false` | Disable all Vlocity Triggers before starting the deployment; triggers are automatically re-enabled after the deployment completes. | -| `maxRetries` | `1` | Number of times to retry the update or insert operation when it fails; defaults to 1 when not set. | -| `retryChunkSize` | `5` | Size of the chunk when retrying deployment of records that previously failed. The deployment limits the number of records inserted or updated to avoid running into limits due to active triggers. Do not change unless you have govern limit errors | -| `lookupFailedDependencies` | `false` | Attempt to lookup dependencies that are part of the deployment but failed to deploy. By setting this to true when part of a datapack fails to deploy the deployment will attempt to lookup an existing record that also matches the lookup requirements. This can help resolve deployment issues whe deploying datapacks from which the parent record cannot be updated, but it does introduce a risk of incorrectly linking records. | -| `purgeMatchingDependencies` | `false` | Purge dependent records after deploying any record. This setting controls whether or not the deployment will delete direct dependencies linked through a matching (not lookup) dependency. This is especially useful to delete for example PCI records and ensure that old relationships are deleted. | -| `purgeLookupOptimization` | `true` | This setting controls how embedded datapacks without matching keys are deleted from the target org when enabled purging of existing records happens in bulk, this is more efficient but in this mode it is not possible to related errors that deleting records to a particular datapack. | -| `deltaCheck` | `false` | When enabled the deployment compares the records that it intends to deploy to the current state of the record in the target org and will only update the fields that are not matching the datapack. | -| `continueOnError` | `false` | Continue the deployment when a fatal error occurs, note that continuing the deployment on fatal errors will result in an incomplete deployment. This setting affects fatal errors such as unable to convert a datapack to valid Salesforce records and should not be enabled on production deployments. | -| `strictOrder` | `false` | When strict order is enabled the deployment will wait for all records in a datapack to complete before proceeding with deploying any dependent datapacks. By default Vlocode determines deployment order based on record level dependencies this allows for optimal chunking improving the overall speed of the deployment. By setting `strictOrder` to `true` Vlocode also enforces that any datapack that is dependent on another datapack is deployed after the datapack it depends on.

Enable this if you are seeing errors during deployment that are caused by records not being deployed in the correct order.

_Note: enabling this impacts deployment performance as the deployment will be split in smaller chunks increasing the number of API calls required to deploy all datapacks._ | -| `allowUnresolvedDependencies` | `false` | When enabled the deployment will not fail when a dependency cannot be resolved. If a record has a dependency that cannot be resolved the record will normally be skipped and marked as failed. Deploying a record with unresolved dependencies can cause errors during deployment or cause the record to be deployed incorrectly.

**Only enable this if you are sure that records can be deployed without all dependencies resolved** | -| `skipLwcActivation` | `false` | When enabled LWC enabled OmniScripts will not get compiled into native LWC components and be deployed to the target org during deployment. Use this if you want to manually compile OmniScripts into LWC or have a batch process ot activate OmniScript LWCs in bulk. | -| `useMetadataApi` | `false` | When set LWC components are deployed using the metadata API instead of the tooling API. The tooling API is usually faster and thus the preferred way to compiled deploy LWC components. Disable this if you need to use the metadata API to deploy LWC components. | -| `remoteScriptActivation` | `false` | When enabled the deployment will activate OmniScripts in the target org using Anonyms Apex. | +| Option | Description | +| ------------ | --- | +| `connection` | A JSForce-compatible connection. If it was not built through `@vlocode/salesforce`, Vlocode will wrap it in a new `vlocode.salesforceConnection` to work around several JSForce bugs that would otherwise break deployments. | +| `sfdxUser` | When set, Vlocode opens a new SFDX-authenticated connection for you. | +| `logger` | Custom log writer. See [Custom logging](#custom-logging). | + +`deploy()` returns a [`DatapackDeployment`](https://vlocode.curlybracket.nl/classes/_vlocode_vlocity_deploy.DatapackDeployment.html) with full info on every deployed record plus warnings and errors (see `getMessages()`). + +## Deploy options + +| Option | Default | Description | +| ----------------------------- | ------- | --- | +| `disableTriggers` | `false` | Disable all Vlocity triggers before starting; they are re-enabled when the deployment completes. | +| `maxRetries` | `1` | Number of times to retry a failed insert/update before giving up. | +| `retryChunkSize` | `5` | Chunk size used when retrying failed records. Reduces the chance of governor-limit failures from active triggers. | +| `lookupFailedDependencies` | `false` | If a dependency record fails to deploy, look up an existing org record matching the lookup requirements. Can resolve issues where the parent record cannot be updated, but risks linking to the wrong record. | +| `purgeMatchingDependencies` | `false` | Delete dependent records (PCIs, attribute assignments, ...) that are linked through a matching dependency before re-deploying. Useful when you want stale child records gone. | +| `purgeLookupOptimization` | `true` | When purging embedded Datapacks without matching keys, delete in bulk. Faster, but errors are not attributable to a specific Datapack. | +| `deltaCheck` | `false` | Compare each record against the org and update only changed fields. | +| `continueOnError` | `false` | Keep going on fatal errors. **Do not enable on production**. | +| `strictOrder` | `false` | Wait for all records in a Datapack to finish before deploying any dependents. Slower but guarantees Datapack-level ordering. Enable if you see deployment errors caused by ordering. | +| `allowUnresolvedDependencies` | `false` | Allow records with unresolved dependencies to deploy anyway. **Only enable if you know the records are safe to deploy without their dependencies.** | +| `skipLwcActivation` | `false` | Do not compile/deploy LWC components for OmniScripts during this deployment. | +| `useMetadataApi` | `false` | Deploy LWC components via the Metadata API instead of the (faster) Tooling API. | +| `remoteScriptActivation` | `false` | Activate OmniScripts via anonymous APEX on the server instead of generating script definitions locally. | ## Custom logging -When using a custom logger it should be passed as an object that has 1 method called `write` which can either be a static member or instance member. Vlocode will pass all log entries to the logger which can then decide how to log them. - -The `write` -function can be async in which case the returned promise is awaited. +Pass a `logger` with a `write(entry)` method — sync or async — and Vlocode will hand every log entry to it. ```ts -export interface LogWriter { - /** - * Write a entry to the log - * @param entry Entry to write - */ - write(entry: LogEntry): void | Promise; -} -``` +import { deploy, LogWriter, LogEntry } from '@vlocode/vlocity-deploy'; -Log entires passed to the logger are described as follows: +const logger: LogWriter = { + write(entry: LogEntry) { + console.log(`[${entry.level}] ${entry.category}: ${entry.message}`); + }, +}; + +await deploy('./datapacks', { sfdxUser: 'alias', logger }); +``` ```ts -export interface LogEntry { +interface LogEntry { level: LogLevel; time: Date; category: string; @@ -136,54 +123,40 @@ export interface LogEntry { ## Matching keys -Matching keys are used to match datapacks tp records in the target org. When determine whether to insert a new record or update an existing record the fields deified in matching key configuration object are used to query for the existing record in the target org. By default the matching keys are loaded from the `DRMatchingKey__mdt` object defined in the target org. The `MatchingKeyFields__c` contains the comma separated list of fields that uniquely records and `vlocity_cmt__ObjectAPIName__c` contains the API name of the SObject for which the matching key is defined. - -All primary Datapack record types should have a matching key. If for any primary datapack record no matching key is defined the deployment will always insert new records and never update existing records. - -When no matching key is defined for an embedded record type (not primary) the deployment will delete all existing records of that type and insert the new records as defined in the datapack. For example when you delete the matching key for ProductChildItem**c the deployment will delete all existing ProductChildItem**c records before deploying the new records. This is useful for child records that cannot be uniquely defined or for which you want to make sure that records deleted from the datapack are also removed from the target org. - -If you define a none-unique matching key the deployment will report a warning when and will not attempt to lookup records to update for that datapack. For example when you define a matching key for `Product2` with only the `ProductFamily` field the deployment will report a warning and will instead create new `Product2` records instead of updating existing ones. - -# Modifying deployment process +Matching keys decide whether the deployment inserts a new record or updates an existing one. They are loaded from the `DRMatchingKey__mdt` custom metadata in the target org: `MatchingKeyFields__c` lists the fields that uniquely identify a record, and `vlocity_cmt__ObjectAPIName__c` (or the OmniStudio equivalent) names the SObject. -Vlocode uses deployment specs to add specific logic per datapack or SObject type. A deployment spec contains Datapack specific logic and allows hooking into the deployment process to manipulate what will be deployed and executes post- and pre-deployment activation logic. +- **Primary Datapack records must have a matching key.** Without one, every deployment inserts a new record. +- **Embedded records without a matching key** are treated as fully owned by the parent: existing rows are deleted and replaced. This is convenient for child records that cannot be uniquely identified or whose deletes should propagate from source (e.g. `ProductChildItem__c`). +- **Non-unique matching keys** trigger a warning and force inserts — Vlocode will not attempt to match. For example, a `Product2` matching key built only from `ProductFamily` is too coarse and would create duplicates. -All deployment specs are maintained in a deployment-spec registry object that contains the spec classes and spec functions that are currently registered. To register a new spec function or object register it in the `DatapackDeploymentSpecRegistry` before starting the deployment. +## Customising the deployment -See the [datapack deployment spec interface](#Datapack-deployment-spec-interface) for the supported hook functions. +Vlocode runs every Datapack through a registry of **deployment specs**. A spec contains Datapack- or SObject-specific logic, and can hook into the deployment lifecycle to mutate records, run pre/post-deployment actions or handle activation. -> Specs for standard datapacks is implemented under the `./deploymentSpecs` folder. +Specs live in the `DatapackDeploymentSpecRegistry`. Register your own before calling `deploy()`. Defaults for the standard Datapacks ship under `./deploymentSpecs`. -## Customization sample +### Example ```js import { DatapackDeploymentSpecRegistry } from '@vlocode/vlocity-deploy'; -// This spec updates all product Names before deployment replacing -// the word `Apple` by `Pear` - does not change the actual datapack +// Rewrite "Apple" to "Pear" in Product2 names before deployment. +// Note: this changes the in-memory datapack, not the source file. DatapackDeploymentSpecRegistry.register( - // A filter can either be a string, or a filter object that filters based on record type - // or based on datapack type { recordFilter: /^Product2$/i }, { - // Preproceses the datapack prior to the deployment; matches all datapacks that have - // Product2 as object and updates the name of a datapack property preprocess(datapack) { - // Update the product names prior to deployment datapack.Name = datapack.Name.replace('Apple', 'Pear'); }, } ); +// Warn on suspicious records after conversion. DatapackDeploymentSpecRegistry.register( { recordFilter: /^Product2$/i }, { afterRecordConversion(records) { - // Validate records and add a warning message when they do not - // match the expectations - this can also be used to make adjustments - // to the records or add dependencies; see the `DatapackDeploymentRecord` documentation - // for all the operations that can be performed on the record object - for (record of records) { + for (const record of records) { if (record.Name?.includes('Apple')) { record.addWarning('you should not deploy apples'); } @@ -192,26 +165,26 @@ DatapackDeploymentSpecRegistry.register( } ); -// or register single functions that will run on a specific hook +// Register a single hook function inline. DatapackDeploymentSpecRegistry.register('Product2', 'afterDeploy', event => { - for (record of event.records) { - console.log(`Record ${record.recordId}: ${record.status} - time: ${record.deployTime}`); + for (const record of event.records) { + console.log(`${record.recordId}: ${record.status} (${record.deployTime}ms)`); } }); ``` -## Overview of hook functions +### Hooks -| Hook | Params | Description | -| ----------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `preprocess` | `VlocityDatapack` | This function executes before a datapack is converted into a set of `DatapackDeploymentRecord`'s and allow changing the datapack data, correct faulty field values that would otherwise cause errors during record conversion or remove certain fields that should not be deployed. This hook can also be used to override certain fields with autogenerated values; i.e. setting the element order and level field of OmniScript elements. | -| `afterRecordConversion` | `readonly DatapackDeploymentRecord[]` | This hook is similar to the `preprocess` hook except that it executes after the datapack to record conversion step. This hook receives list of records that contains all the records generated for a single datapack; it is not possible to remove/drop any record but individual records can be manipulated. **Note** At this point dependencies are not yet resolved | -| `beforeDeploy` | `DatapackDeploymentEvent` | This hook is called before deploying the first record in a datapack, and is only called once very datapack in the deployment. Use this hook to execute and pre-deployment actions. This action is comparable with the `pre-step` job from the Vlocity tools library. | -| `afterDeploy` | `DatapackDeploymentEvent` | This hook is called after all records of a datapack are deployed and will only be called once for every datapack in the deployment. Use this hook to execute datapack activation logic; it is comparable to `post-step` in Vlocity tools and should also execute any activation logic if required. | -| `beforeDeployRecord` | `readonly DatapackDeploymentRecord[]` | Executed just before the records are being deployed; the event contains a readonly array of records. At this stage values for the records can still be manipulated. This hook point should only be used to run logic that depends on all dependencies on individual record level are resolved. | -| `afterDeployRecord` | `readonly DatapackDeploymentRecord[]` | Executes after a group of records is deployed, at this stage it is not possible to change any field value anymore. The hook point can be used to run post-deployment validations or post-deployment activation processes. | +| Hook | Params | When | +| ----------------------- | ------------------------------------- | --- | +| `preprocess` | `VlocityDatapack` | Before the Datapack is converted into records. Best place to scrub bad field values or auto-populate fields (e.g. OmniScript element ordering). | +| `afterRecordConversion` | `readonly DatapackDeploymentRecord[]` | After conversion, before dependency resolution. You can mutate records but not add or remove them. | +| `beforeDeploy` | `DatapackDeploymentEvent` | Once per Datapack, just before its first record is deployed. Equivalent to a Vlocity *pre-step*. | +| `afterDeploy` | `DatapackDeploymentEvent` | Once per Datapack, after all its records are deployed. Equivalent to a Vlocity *post-step*. Run activation logic here. | +| `beforeDeployRecord` | `readonly DatapackDeploymentRecord[]` | Just before a batch of records is sent to Salesforce. All record-level dependencies are resolved at this point. | +| `afterDeployRecord` | `readonly DatapackDeploymentRecord[]` | After a batch of records is deployed. Use for post-deployment validation; record fields are no longer mutable. | -## Datapack deployment spec interface +### Spec interface ```ts export type DatapackFilter = diff --git a/packages/vlocity/README.md b/packages/vlocity/README.md index 5b13411a..d995b376 100644 --- a/packages/vlocity/README.md +++ b/packages/vlocity/README.md @@ -1,6 +1,25 @@ [![CI](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml/badge.svg)](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml) -[![GitHub top language](https://img.shields.io/github/languages/top/codeneos/vlocode.svg?logo=github)](https://github.com/Codeneos/vlocode) -[![Bugs](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/bugs.svg?color=lightgray&label=bugs&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) -[![Vulnerabilities](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/vulnerabilities.svg?label=vulnerabilities&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) +![NPM Version](https://img.shields.io/npm/v/%40vlocode%2Fvlocity) -# **@vlocode/vlocity** Shared library for Vlocity related functionality +# @vlocode/vlocity — shared Vlocity / OmniStudio building blocks + +The shared domain layer used by [`@vlocode/vlocity-deploy`](../vlocity-deploy), [`@vlocode/omniscript`](../omniscript), the [`@vlocode/cli`](../cli) tool and the Vlocode VS Code extension. If you are building your own OmniStudio tooling on top of `@vlocode`, this is most likely a transitive dependency you do not need to import directly. + +## What's inside + +- **Datapack types** — type-safe representations of Vlocity Datapacks +- **Datapack loader** — load Datapack folder structures from disk +- **Matching key service** — resolves `DRMatchingKey__mdt` records and applies them when comparing source records against the target org +- **Namespace handling** — bridges the `vlocity_cmt__` and `omnistudio__` namespaces transparently +- **Vlocity manifest helpers** — produce and parse the Vlocity build manifest format + +## Install + +```shell +npm install @vlocode/vlocity +``` + +## See also + +- [`@vlocode/vlocity-deploy`](../vlocity-deploy) — the deployment engine that consumes these types +- [`@vlocode/omniscript`](../omniscript) — the OmniScript → LWC compiler diff --git a/packages/vscode-extension/README.md b/packages/vscode-extension/README.md index 9fab23f2..a0e932d8 100644 --- a/packages/vscode-extension/README.md +++ b/packages/vscode-extension/README.md @@ -3,106 +3,188 @@ [![CI](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml/badge.svg)](https://github.com/Codeneos/vlocode/actions/workflows/ci.yml) [![GitHub top language](https://img.shields.io/github/languages/top/codeneos/vlocode.svg?logo=github)](https://github.com/Codeneos/vlocode) [![Downloads](https://badgen.net/vs-marketplace/d/curlybracket.vlocode)](https://marketplace.visualstudio.com/items?itemName=curlybracket.vlocode) -[![Bugs](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/bugs.svg?color=lightgray&label=bugs&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) -[![Vulnerabilities](https://img.shields.io/sonar/https/sonarcloud.io/curlybracket.vlocode/vulnerabilities.svg?label=vulnerabilities&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAolBMVEUAAAD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgD%2FZgCXdjhZAAAANXRSTlMA%2Bg335ykFAwnr7hDZON7Ie1ZDMfTUmIUUSSLPoVAa4r6K8rtyXD62gG2xpsKSjnZpYx6qTp5XIo8AAAOWSURBVFjD7VbZtqIwEGSVRXYQAVFBFvf16v%2F%2F2tgJKsYEvPM4Z%2FLiwV7SXV2phPu3lyB71fnserLwN9HD%2BGBL4u2%2BRMk%2BeMJvw887CH6uIKuGvwhXvIK%2FEYtf1sq38epRu1GWtFa%2FLH%2FPNxFFvq6q9aGQ8LeYC19hH2L30VFWm4p8Z4Tb2H%2BRYbBC%2B2urWfvfy1hHGZx%2BHNwFeBox4alMDfhfv%2FbFJxNUvvlpqVEGe9aTYAxe85pmihGWTne8bEGnJ7qx5KG5pDNBCZssBcZ8M7CeOkcILuKUCTAP6bvo5GuAE5P1ESAsyR0JKqhxzLYfACG3ZwY8dMDsoWcOKXDFZ9tNYFnYQeMNkPh09fzZgD5loMKWfYxrREOeF3VjU%2FqUHMn8bp8w5Elwl4tba2nbTwWRNSRPBUWeFHMjkgqirckMXuPDFx5hUtcSGU4b%2BemV3BHeSHpoUut2uirL8XYSwNfCJEDetjQyjFrtNyJmjE3cnBJ54b3dgmhVBgytfIRTpENChPQ8aYNSHxzy4DkoTrmMseju1XcRmg64L866eL0nj1ER4rkZ7oghQuScgadNWz5ijIVBzlkiRCDoQKOB25Dagqhw8ECGP%2FXGHwOEwKPvCj4184HMpk%2Fwo72IGpWfzEEjze8WGwqL%2BwrIMbNafrUO52LGefCb9RUwtFG82ybvBnaecsd%2BrQYEfgD0d6lZ4x6gFdGj3%2FLDV2H%2B0tr4FHVZcjaUllDnvppk8etrRqrxzAJUOQNIGLEEcHTpwAVpNIfSRCyFDcwOZu6ACbgC6o25Quj0VrAjhINAuWInuGAMUtiHyqMp333L1AFQmCuZbr7WSTHMoBVngpsd0UCCCetm50W88DihgB5c5mNjz0oQB3hnjNWOVoKpA8Amo4Dl4wwkBupFoR4AgGnIfq7M5ScYOq0JD9jO5wPmgwmDH%2B2Qpk0%2FKyjxa32lfsYjRZtcmo0kfJERE4vyoHnihgRT1TOK0J97ngLk92MOWk5XKKxZtiu0CvNTXNlReQmu2FzIbgLlKoJ8XuLtdQ0XUZxkAfzVyzSV8N02Vtvd6s2NN8%2FSMNzaEo%2B%2F525sPG5a%2BycM08xqLAtHfX8Kj26UlZmgRTzFYlTkbJK9RjrNHUSvYWmQFj2UKbQxQ6u1Fz8ay8ojuTMR24nTekAX0aQKd5am65KRHaZvo4vivDAkfaFZdnhOKOEt7ZR9XwYBJZeKLJf7LP4vYv0BK5jBy9A2z3IAAAAASUVORK5CYII%3D)](https://sonarcloud.io/dashboard?id=curlybracket.vlocode) - -# **Vlocode**: Vlocity/Salesforce development integration for Visual Studio Code - -This extension provides functionality for deploying, extracting, and refreshing **Vlocity metadata** with Visual Studio Code. -It is targeted at **Vlocity/Salesforce developers** who work with **Vlocity (Salesforce Industries)** and **Salesforce Metadata**. - -Vlocode makes your life as a _Salesforce_ or _Vlocity_ developer easier by providing you with a set of powerful commands to work with both Salesforce as well as Vlocity (Salesforce Industries) Metadata. - -_Vlocode is an additive extension to the SFDX extension pack from Salesforce_ - -## Notable features of **Vlocode** - -- Direct access to the **Developer/Debug Logs** through a new UI pannel. -- **Auto creates -meta.xml files** for you when you create an APEX class or APEX Trigger -- Allows you to **open** exported **Metadata directly in Salesforce** through a context menu action -- Change the debug log level on the connected org -- **Delete all debug logs** on the connected org directly from the \*Developer/Debug Logs panel -- Execute anonymous APEX and directly open the log as if you were working from the developer console -- Full support for packaging and **deploying SFDX** metadata -- Powerful **Vlocity Metadata browser** to export and open Vlocity Metadata -- Commands to directly execute common **Vlocity CMT Admin commands** such as Refresh Product Hierarchy - -This extension embeds the popular libraries such as JSForce, SFDX (_@salesforce/core_) and the Vlocity build tools library allowing you to directly manipulate your Salesforce org from within your IDE. As opposed to the official SFDX extension Vlocode aims at providing a more guide and integrated experience. You can (and should) use Vlocode next to the official SFDX extension pack. - -All settings for Vlocode in the `.vscode` settings file making it easy to maintain and change. You can use a special `.vlocode` config file to define project defaults which can be versioned in git. See the bottom of this readme which describes how to use a `.vlocode` config file. - -## All Features - -### Salesforce - -- **Export metadata** export all Salesforce metadata from the Command Pallet - ![Developer logs](packages/vscode-extension/resources/exportMetadata.gif) -- **Auto create and update -meta.xml files** automatically rename and create _-meta.xml_ files when you create or rename APEX classes -- **Advance metadata deployments** - - Support deployment of both **SFDX** and **Classic** Metadata format - - Support mixed source code deployment with Netadata defined both in SFDX format as well as in classic format -- **Support LWC/Aura** support for both LWC and Aura deployments -- **Deploy on save** automatically deploy Salesforce Metadata to the connected org on save -- **Deploy multiple metadata files** deploy one or more Salesforce Metadata components directly from within VSCode -- **Refresh/Export metadata** refresh or export one or more Salesforce Metadata components with a single click of your mouse -- **Easy creation of APEX classes** automatically generate a boiler plate class definitions and -meta.xml file for APEX Classes, Triggers and more -- **Execute anonymous** execute anonymous APEX with a configurable log level and profiling and directly open the log in VSCode after execution -- **Execute Salesforce REST APIs** easy Salesforce RESP API testing directlly opening the response in VScode -- **Delete metadata from org** delete Salesforce Metadata components from your org from within vscode -- ** Salesforce Logs viewer** using the integrated Log viewer you can view and open Salesforce debug logs directly from VSCode - ![Developer logs](packages/vscode-extension/resources/developerLogs.png) - -### Vlocity - -- **Retrieve & refresh** Vlocity datapacks from within Visual Studio Code simplifying your workflow -- **Deploy** exported Vlocity datapacks with a single click from within Visual Studio Code -- **Export** any datapack enabled object directly from within VSCode. -- **Run Yaml Job** Run any YAML job file directly from VSCode. - ![Datapack export](packages/vscode-extension/resources/exportDatapack.gif) -- **Open in Salesforce** directly open any Vlocity object in Salesforce. -- **Clone Datapack** clone any Datapack object from your IDE, usefull for cloning products or templates directly from VSCode -- **Rename Datapack** change the name of a Datapack and rebuild the file structure to match the new name -- **Rebuild parentkeys** rebuild and verify your source code for missing dependencies and rebuild the dependency graph -- **Check Integrity** Check datapack integrity by finding missing references and rebuilding ParentKey files -- **Admin Commands** Vlocode integrates common admin commands for Vlocity: - - **Refresh Pricebook** Refreshes pricebook entries on the currently connected Salesforce org - - **Refresh Product Hierarchy** Refresh the product hierarchy cache for the Vlocity CPQ - - **Update Product Attributes (JSON)** Refresh the product attribute JSON definitions based on the attribute assignments - ![Admin Commands](packages/vscode-extension/resources/adminCommands.gif) -- **Datapack explorer** view all exportable objects available in the connected org and export them with a single click - ![Datapack explorer](packages/vscode-extension/resources/exploreDatapack.gif) -- **Easy setup** Simplified setup based on SFDX using session tokens instead; no need to acquire security tokens or copy-past passwords and usernames around. -- **SFDX Support** username or alias to login to Salesforce +[![Release](https://badgen.net/github/release/Codeneos/vlocode/stable)](https://github.com/Codeneos/vlocode/releases) -## Requirements +# Vlocode — Salesforce Industries & OmniStudio (Vlocity) for VS Code + +**Vlocode is the fast, opinionated VS Code extension for Salesforce Industries / OmniStudio (Vlocity) and Salesforce metadata developers.** It deploys, retrieves and activates everything you work with day to day — Datapacks, OmniScripts, FlexCards, DataRaptors, APEX, LWC, Aura and standard metadata — right from the editor. + +Vlocode is **additive** to the official [Salesforce Extension Pack](https://marketplace.visualstudio.com/items?itemName=salesforce.salesforcedx-vscode). Install both: keep the SFDX tooling you know and add Vlocode's faster deploy/retrieve flow and full OmniStudio support on top. + +--- + +## Why Vlocode? + +- :rocket: **Up to 10–20× faster** Datapack deployments than the Vlocity Build Tools / DX +- :package: **One extension** for SFDX metadata *and* OmniStudio/Vlocity content +- :mag: **True delta** detection — deploy only what actually changed in the org, no git diff required +- :zap: **Client-side OmniScript & LWC compilation** with no server-side APEX round-trips +- :wrench: **Rich UI** — Datapack Explorer, Salesforce Logs panel, Data Mapper editor and Datapack editor +- :bookmark_tabs: **Per-project config** via a `.vlocode` file you can commit to git +- :key: **Uses your existing SFDX auth** — no security tokens, no copy-pasted passwords + +--- + +## Feature highlights + +### Salesforce metadata +- Deploy, retrieve, refresh and delete metadata from the editor, explorer and command palette +- Mixed-format support — deploy SFDX *and* classic Metadata API source in a single project +- Deploy-on-save with a deployment queue you can pause, resume and clear +- Auto-create and rename `-meta.xml` files when you create or rename APEX classes and triggers +- Generate boilerplate for APEX classes, triggers, Lightning Web Components and Aura bundles +- Execute Anonymous APEX with configurable log level and profiling; the log opens automatically in the editor +- Send requests against the Salesforce REST API straight from a `.sfhttp` file +- Add or remove APEX classes, fields and objects from one or more Profiles in one action +- Highlight APEX unit-test coverage inline in the editor + +![Salesforce metadata workflow](https://raw.githubusercontent.com/Codeneos/vlocode/main/packages/vscode-extension/resources/salesforceDemo.gif) + +### Salesforce Logs panel +- View, filter and open Apex Debug Logs straight from a dedicated VS Code panel +- Change the debug log level on the connected org without leaving VS Code +- Toggle between *your* logs and *all* logs on the org +- Clear every log on the org with a single click + +![Salesforce Logs panel](https://raw.githubusercontent.com/Codeneos/vlocode/main/packages/vscode-extension/resources/developerLogs.png) + +### Vlocity / OmniStudio Datapacks +- Deploy, refresh, export, rename and clone any Datapack from the explorer or editor +- Browse and export every exportable object in the org from the **Datapack Explorer** sidebar +- Open any Datapack record directly in the connected org +- Rebuild ParentKey files and verify Datapack integrity +- Import Vlocity multipacks and run any YAML Datapack job +- Visual **Datapack** and **DataMapper** editors for `*_DataPack.json` and DataRaptor / OmniDataTransform files + +![Datapack Explorer](https://raw.githubusercontent.com/Codeneos/vlocode/main/packages/vscode-extension/resources/exploreDatapack.gif) + +### OmniScripts, FlexCards & IntegrationProcedures +- **Generate an LWC** from any OmniScript — locally, in seconds, no APEX activation needed +- (Re-)activate OmniScripts and FlexCards from the context menu +- Convert OmniScript, FlexCard, IntegrationProcedure and DataRaptor runtimes between Vlocity (`vlocity_cmt__`) and standard OmniStudio (`omnistudio__`) +- Scaffold a new OmniScript LWC project structure + +> :camera: _Placeholder — add a screenshot of the_ `OmniScript: Generate LWC` _command running on a sample OmniScript._ + +### Industries / OmniStudio admin +- **Industries Administration Console** — the most common admin commands in one quick-pick +- Refresh Pricebook, refresh Product Hierarchy, update Product Attribute JSON, clear Platform Cache + +![Industries admin commands](https://raw.githubusercontent.com/Codeneos/vlocode/main/packages/vscode-extension/resources/adminCommands.gif) + +### Visual editors +- **Datapack editor** — a custom editor that opens any `*_DataPack.json` file as a structured form +- **DataMapper editor** — a custom editor for DataRaptor and OmniDataTransform definitions +- One click to flip between the visual editor and the underlying JSON source + +> :camera: _Placeholder — add a side-by-side screenshot of the Datapack Editor (left) and DataMapper Editor (right)._ + +--- + +## Getting started + +1. Install the [Salesforce Extension Pack](https://marketplace.visualstudio.com/items?itemName=salesforce.salesforcedx-vscode). +2. Install **Vlocode** from the Marketplace. +3. Open a folder that contains a Salesforce / OmniStudio project. +4. Run **`Vlocode: Select Salesforce Org`** from the command palette and pick an authenticated SFDX org — or authenticate a new one. +5. Right-click any metadata or Datapack file to deploy, refresh, export or open it in the org. + +Vlocode uses your existing SFDX/Salesforce CLI authentication. No security-token juggling, no password fields. + +--- -- Basic knowledge of Vlocity datapacks -- Access to an Salesforce instance with the Vlocity managed package installed +## Typical workflows -## Using a `.vlocode` config rule +### Deploy a single APEX class on save +```jsonc +// .vscode/settings.json +{ + "vlocity.salesforce.enabled": true, + "vlocity.salesforce.deployOnSave": true +} +``` +Save any `*.cls` or `*-meta.xml` file and Vlocode queues a delta deploy in the background. The deployment queue is visible in the status bar — you can pause, resume or clear it from the command palette. + +### Deploy a Datapack folder from the context menu +Right-click the Datapack folder in the explorer → **Datapack: Deploy to Org**. Vlocode resolves dependencies client-side and deploys records in the optimal order. + +### Export metadata via the command palette +Open the command palette → **Salesforce: Export/Retrieve metadata from Org** → pick the metadata types you want. + +![Export metadata](https://raw.githubusercontent.com/Codeneos/vlocode/main/packages/vscode-extension/resources/exportMetadata.gif) + +### Export a Datapack from the org +Open the command palette → **Datapack: Export from Org**, or use the Datapack Explorer to pick a record visually. + +![Export a Datapack](https://raw.githubusercontent.com/Codeneos/vlocode/main/packages/vscode-extension/resources/exportDatapack.gif) + +### Execute Anonymous APEX +Open an `.apex` scratch file, write a snippet, run **`Salesforce: Execute Anonymous APEX`** and the debug log opens automatically. + +```apex +// scratch.apex +List accs = [SELECT Id, Name FROM Account LIMIT 5]; +for (Account a : accs) System.debug(a.Name); +``` + +### Call a REST endpoint from a `.sfhttp` file +```http +GET /services/data/v60.0/sobjects/Account/describe HTTP/1.1 +``` +Right-click → **Salesforce: Execute REST API**. The response opens in a new editor tab. -Instead of configuring Vlocode through VSCodes workspace and user level settings you can also override configuration settings using a workspace-folder `.vlocode`-file. This allows to force a certain configuration value and can be usefull to ensure all developers on the project use the same configuration for exporting _vlocity_ and _Salesforce_ metadata +### Generate an LWC from an OmniScript +Right-click any OmniScript folder → **OmniScript: Generate LWC**. Vlocode compiles the script definition locally and emits a ready-to-deploy LWC bundle — no Vlocity APEX activation required. -**Sample of a `.vlocode` configuration-file** +--- + +## Project-level configuration: `.vlocode` + +Drop a `.vlocode` file at the workspace root to share defaults across your team. Values here override the VS Code user/workspace settings and can be committed to git. ```json { "customJobOptionsYaml": "./vlocity/dataPacksJobs/default.yaml", "projectPath": "./vlocity/src", "salesforce": { - "apiVersion": "48.0" + "apiVersion": "60.0" } } ``` -## Extension Settings +--- + +## Settings reference + +The settings you will reach for most often: + +| Setting | Description | +| --- | --- | +| `vlocity.projectPath` | Path to the folder containing your Vlocity Datapacks, relative to the workspace root (e.g. `./vlocity` or `./datapacks`). | +| `vlocity.customJobOptionsYaml` | Path to a Vlocity job YAML used during deployment and export. See the [Vlocity Build options](https://github.com/vlocityinc/vlocity_build#additional-command-line-options). | +| `vlocity.sfdxUsername` | SFDX username or alias. When set, legacy username/password/loginUrl settings are ignored. | +| `vlocity.salesforce.enabled` | Enables the Salesforce metadata commands (deploy / refresh / retrieve / ...). | +| `vlocity.salesforce.apiVersion` | Salesforce API version used for all metadata operations. | +| `vlocity.salesforce.deployOnSave` | Automatically deploy modified metadata files on save. | +| `vlocity.deployOnSave` | Same, for Vlocity Datapack files. | +| `vlocity.deploy.lwcActivation` | Whether OmniScript LWCs are compiled and activated client-side during a Datapack deploy. | +| `vlocity.deploy.lwcDeploymentType` | `tooling` (default, fastest) or `metadata`. | +| `vlocity.deploy.allowUnresolvedDependencies` | Allow deployments to continue when a dependency cannot be resolved. | + +All extension settings live under `vlocity.*` — type `vlocity` into the VS Code settings UI to see the full list. + +--- + +## Requirements + +- VS Code 1.95 or newer +- The [Salesforce Extension Pack](https://marketplace.visualstudio.com/items?itemName=salesforce.salesforcedx-vscode) (SFDX authentication is shared with Vlocode) +- A Salesforce org with the **Vlocity / Salesforce Industries** managed package installed if you want to use the Datapack / OmniStudio features + +## Issues and feedback + +Found a bug or missing feature? Please [open an issue on GitHub](https://github.com/Codeneos/vlocode/issues). PRs welcome. -This extension contributes the following settings: +## License -- `vlocity.projectPath`: Path to the folder containing the Vlocity datapacks relative to the workspace's root folder, for example: - - `./vlocity` - - `./datapacks` -- `vlocity.verbose`: Enable verbose logging to the output window -- `vlocity.activate`: Automatically activate deployed datapacks -- `vlocity.customJobOptionsYaml`: Path to the custom YAML that is used during deployment and export, see the official Vlocity Build repository for [documentation](https://github.com/vlocityinc/vlocity_build#additional-command-line-options) on the format of this file. -- `vlocity.sfdxUsername`: SFDX username; when this is specified the username, password, loginUrl and instanceUrl are ignored. +MIT — see [LICENSE](./LICENSE). diff --git a/packages/vscode-webviews/README.md b/packages/vscode-webviews/README.md index 366c0ac2..5bbf1bc8 100644 --- a/packages/vscode-webviews/README.md +++ b/packages/vscode-webviews/README.md @@ -1,8 +1,13 @@ -# VS Code Webviews +# @vlocode/vscode-webviews -Angular applications rendered inside the VS Code extension webview host. +Angular applications rendered inside the Vlocode VS Code extension's webview host. This package owns multiple webview build targets so shared styling and reusable UI code can stay in one place, without spinning up a new workspace package for every editor. -This package owns multiple webview build targets so shared styling and reusable UI code can stay in one place without adding a new workspace package for every editor. +Currently shipped webviews: + +- **Datapack editor** — structured editor for `*_DataPack.json` files +- **DataMapper editor** — structured editor for DataRaptor / OmniDataTransform definitions + +> This is an internal package — it is not published to npm and is not intended to be consumed outside of this repository. ## Build @@ -12,7 +17,7 @@ pnpm --filter @vlocode/vscode-webviews build:datapack pnpm --filter @vlocode/vscode-webviews build:datamapper ``` -Build outputs are written to: +Outputs are written into the VS Code extension package so they ship as static assets: -- `packages/vscode-extension/resources/datapack-editor` -- `packages/vscode-extension/resources/datamapper-editor` +- `packages/vscode-extension/resources/datapack-editor` +- `packages/vscode-extension/resources/datamapper-editor`