Skip to content

Commit

Permalink
feat(plugin): add test vendor support and improve CLI selection logic (
Browse files Browse the repository at this point in the history
…#2846)

- Introduce 'test' vendor to various vendor constants
- Update CLI to handle an 'all' selection for projects and apps
- Refactor environment file mapping logic to use the final selected items

(Your vendor constants are so well-rounded, they could run for office)

Co-authored-by: Tomer Shvadron <[email protected]>
  • Loading branch information
alonp99 and tomer-shvadron authored Nov 20, 2024
1 parent 4cfcf8a commit 09b7a7a
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const INDIVIDUAL_SCREENING_VENDORS = {

export const COMPANY_SCREENING_VENDORS = {
'asia-verify': 'asia-verify',
test: 'test',
} as const;

export const KYC_VENDORS = {
Expand All @@ -20,11 +21,13 @@ export const MERCHANT_MONITORING_VENDORS = {
export const UBO_VENDORS = {
'asia-verify': 'asia-verify',
kyckr: 'kyckr',
test: 'test',
} as const;

export const REGISTRY_INFORMATION_VENDORS = {
'asia-verify': 'asia-verify',
kyckr: 'kyckr',
test: 'test',
} as const;

export const EMAIL_TEMPLATES = {
Expand Down Expand Up @@ -174,7 +177,7 @@ type UboKyckrOptions = {

type RegistryInformationAsiaVerifyOptions = {
pluginKind: 'registry-information';
vendor: 'asia-verify';
vendor: 'asia-verify' | 'test';
defaultCountry?: string;
};

Expand Down Expand Up @@ -257,6 +260,53 @@ const getKycEntityMapping = (takeEntityDetailFromKyc: boolean) => {

export const BALLERINE_API_PLUGIN_FACTORY = {
[BALLERINE_API_PLUGINS['registry-information']]: {
[REGISTRY_INFORMATION_VENDORS['test']]: (options: RegistryInformationAsiaVerifyOptions) => ({
name: 'businessInformation',
displayName: 'Registry Information',
pluginKind: 'registry-information',
vendor: 'test',
url: {
url: `{secret.UNIFIED_API_URL}/companies-v2/{country}/{entity.data.registrationNumber}`,
options: {
country: options.defaultCountry ?? '{entity.data.country}',
},
},
method: 'GET',
persistResponseDestination: 'pluginsOutput.businessInformation',
headers: { Authorization: 'Bearer {secret.UNIFIED_API_TOKEN}' },
request: {
transform: [
{
transformer: 'jmespath',
mapping: `merge(
{ vendor: 'test' },
entity.data.country == 'HK' && {
callbackUrl: join('',['{secret.APP_API_URL}/api/v1/external/workflows/',workflowRuntimeId,'/hook/VENDOR_DONE','?resultDestination=pluginsOutput.businessInformation.data&processName=kyb-unified-api'])
}
)`, // jmespath
},
],
},
response: {
transform: [
{
mapping:
"merge({ name: 'businessInformation', status: reason == 'NOT_IMPLEMENTED' && 'CANCELED' || error != `null` && 'ERROR' || jurisdictionCode == 'HK' && 'IN_PROGRESS' || 'SUCCESS' }, @)",
transformer: 'jmespath',
},
{
mapping: [
{
method: 'setTimeToRecordUTC',
source: 'invokedAt',
target: 'invokedAt',
},
],
transformer: 'helper',
},
],
},
}),
[REGISTRY_INFORMATION_VENDORS['asia-verify']]: (
options: RegistryInformationAsiaVerifyOptions,
) => ({
Expand Down Expand Up @@ -481,6 +531,48 @@ export const BALLERINE_API_PLUGIN_FACTORY = {
],
},
}),
[COMPANY_SCREENING_VENDORS['test']]: (options: CompanySanctionsAsiaVerifyOptions) => ({
name: 'companySanctions',
pluginKind: 'company-sanctions',
vendor: 'test',
url: {
url: `{secret.UNIFIED_API_URL}/companies/{country}/{entity.data.companyName}/sanctions`,
options: {
country: options.defaultCountry ?? '{entity.data.country}',
},
},
headers: { Authorization: 'Bearer {secret.UNIFIED_API_TOKEN}' },
method: 'GET' as const,
displayName: 'Company Sanctions',
persistResponseDestination: 'pluginsOutput.companySanctions',
request: {
transform: [
{
mapping: "{ vendor: 'test' }",
transformer: 'jmespath',
},
],
},
response: {
transform: [
{
mapping:
"merge({ name: 'companySanctions', status: contains(['NOT_IMPLEMENTED', 'NOT_AVAILABLE'], reason) && 'CANCELED' || error != `null` && 'ERROR' || 'SUCCESS' }, @)",
transformer: 'jmespath',
},
{
mapping: [
{
method: 'setTimeToRecordUTC',
source: 'invokedAt',
target: 'invokedAt',
},
],
transformer: 'helper',
},
],
},
}),
},
[BALLERINE_API_PLUGINS['merchant-monitoring']]: {
[MERCHANT_MONITORING_VENDORS['ballerine']]: (options: MerchantMonirotingOptions) => ({
Expand Down Expand Up @@ -573,6 +665,51 @@ export const BALLERINE_API_PLUGIN_FACTORY = {
],
},
}),
[UBO_VENDORS['test']]: (options: UboAsiaVerifyOptions) => ({
name: 'ubo',
pluginKind: 'ubo',
vendor: 'test',
displayName: 'UBO Check',
url: {
url: `{secret.UNIFIED_API_URL}/companies/{country}/{entity.data.registrationNumber}/ubo`,
options: {
country: options.defaultCountry ?? '{entity.data.country}',
},
},
method: 'GET',
persistResponseDestination: 'pluginsOutput.ubo',
headers: { Authorization: 'Bearer {secret.UNIFIED_API_TOKEN}' },
request: {
transform: [
{
transformer: 'jmespath',
mapping: `{
vendor: 'test',
callbackUrl: join('',['{secret.APP_API_URL}/api/v1/external/workflows/',workflowRuntimeId,'/hook/VENDOR_DONE','?resultDestination=pluginsOutput.ubo.data&processName=ubo-unified-api'])
}`, // jmespath
},
],
},
response: {
transform: [
{
mapping:
"merge({ name: 'ubo', status: reason == 'NOT_IMPLEMENTED' && 'CANCELED' || error != `null` && 'ERROR' || 'IN_PROGRESS' }, @)",
transformer: 'jmespath',
},
{
mapping: [
{
method: 'setTimeToRecordUTC',
source: 'invokedAt',
target: 'invokedAt',
},
],
transformer: 'helper',
},
],
},
}),
[UBO_VENDORS['kyckr']]: (options: UboKyckrOptions) => ({
name: 'ubo',
pluginKind: 'ubo',
Expand Down
36 changes: 26 additions & 10 deletions scripts/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ async function main() {
type: 'checkbox',
name: 'selectedItems',
message: 'Select projects and apps to run:',
choices: projectsAndApps,
choices: [{ name: 'All', value: 'all' }, new inquirer.Separator(), ...projectsAndApps],
default: projectsAndApps.map(item => item.value),
},
{
Expand All @@ -71,6 +71,11 @@ async function main() {
let useNgrok = false;
let resetDatabase = false;

// Convert 'all' selection to all projects
const finalSelectedItems = selectedItems.includes('all')
? projectsAndApps.map(item => item.value)
: selectedItems;

if (mode === 'advanced') {
const advancedOptions = await inquirer.prompt([
{
Expand All @@ -90,9 +95,9 @@ async function main() {
useNgrok = advancedOptions.useNgrok;

if (advancedOptions.useCommonEnv) {
envFiles = Object.fromEntries(selectedItems.map(item => [item, '.env']));
envFiles = Object.fromEntries(finalSelectedItems.map(item => [item, '.env']));
} else {
for (const item of selectedItems) {
for (const item of finalSelectedItems) {
const projectEnvFiles = getEnvFiles(item);
const { envFile } = await inquirer.prompt([
{
Expand All @@ -107,11 +112,11 @@ async function main() {
}
}
} else {
envFiles = Object.fromEntries(selectedItems.map(item => [item, '.env']));
envFiles = Object.fromEntries(finalSelectedItems.map(item => [item, '.env']));
}

// Check if workflows-service is selected
if (selectedItems.some(item => item.includes('workflows-service'))) {
if (finalSelectedItems.some(item => item.includes('workflows-service'))) {
const { resetDatabaseConfirm } = await inquirer.prompt([
{
type: 'confirm',
Expand All @@ -123,9 +128,11 @@ async function main() {
resetDatabase = resetDatabaseConfirm;
}

const projectFilter = selectedItems.map(item => item.split('/')[1]).join(',');
const workflowsServiceIncluded = selectedItems.some(item => item.includes('workflows-service'));
const appsIncluded = selectedItems.some(item => item.includes('apps/'));
const projectFilter = finalSelectedItems.map(item => item.split('/')[1]).join(',');
const workflowsServiceIncluded = finalSelectedItems.some(item =>
item.includes('workflows-service'),
);
const appsIncluded = finalSelectedItems.some(item => item.includes('apps/'));

let command = `nx run-many --target=${runMode} --projects=${projectFilter
.split(',')
Expand All @@ -137,25 +144,34 @@ async function main() {
}

if (workflowsServiceIncluded && appsIncluded) {
command = `nx run @ballerine/workflows-service:${runMode} & wait-on http://localhost:3000/api/v1/_health/ready && ${command}`;
// Remove workflows-service from the command since we'll run it separately
const filteredProjects = projectFilter
.split(',')
.filter(project => project !== 'workflows-service')
.map(project => `@ballerine/${project}`)
.join(',');

const filteredCommand = `nx run-many --target=${runMode} --projects=${filteredProjects}`;
command = `nx run @ballerine/workflows-service:${runMode} & wait-on http://localhost:3000/api/v1/_health/ready && ${filteredCommand}`;
}

const timestamp = new Date().toISOString().replace(/:/g, '-');
const logFile = path.join(logsDir, `nx_run_${timestamp}.log`);
const logStream = fs.createWriteStream(logFile, { flags: 'a' });

console.log(`Running command: ${command}`);
console.log('Using .env files:');
Object.entries(envFiles).forEach(([project, envFile]) => {
console.log(` ${project}: ${envFile}`);
});
console.log(`Logs: ${logFile}`);

if (useNgrok) {
console.log('Establishing ngrok tunnel...');
const url = await ngrok.connect(3000);
console.log(`ngrok tunnel established: ${url}`);
}

console.log(`Executing command: ${command}`);
const child = spawn(command, {
shell: true,
cwd: path.join(__dirname, '..'),
Expand Down

0 comments on commit 09b7a7a

Please sign in to comment.