@benup/bensdk 1.0.8 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -4
- package/bin/src/cli/app.js +7 -8
- package/bin/src/cli/app.js.map +1 -1
- package/bin/src/cli/init.js +49 -33
- package/bin/src/cli/init.js.map +1 -1
- package/bin/src/cli/templates/benefit-definition.template.ts +48 -2
- package/bin/src/cli/templates/benefit-definition.types.template.ts +29 -1
- package/bin/src/cli/templates/bensdk-cli/generate.ts +33 -29
- package/bin/src/cli/templates/bensdk-cli/lib/benefit-definition.schema.ts +20 -3
- package/bin/src/cli/templates/bensdk-cli/lib/state-machine.ts +65 -60
- package/bin/src/cli/templates/bensdk-cli/templates/state.handler.template.ts +6 -7
- package/bin/src/cli/templates/bensdk-cli/validate.ts +22 -20
- package/bin/src/cli/templates/bensdk-lib/types/action-base.type.ts +193 -181
- package/bin/src/cli/templates/bensdk-lib/types/action.types.ts +11 -9
- package/bin/src/cli/templates/bensdk-lib/types/base-deduction.type.ts +165 -175
- package/bin/src/cli/templates/bensdk-lib/types/base-dependent.type.ts +178 -0
- package/bin/src/cli/templates/bensdk-lib/types/base-recharge.type.ts +162 -172
- package/bin/src/cli/templates/bensdk-lib/types/benefits-definition.type.ts +49 -34
- package/bin/src/cli/templates/bensdk-lib/types/grant-revoke.type.ts +157 -167
- package/bin/src/cli/templates/bensdk-local-server/app.ts +43 -48
- package/bin/src/cli/templates/bensdk-viewer/.svelte-kit/tsconfig.json +37 -48
- package/bin/src/cli/templates/bensdk-viewer/src/app.d.ts +7 -7
- package/bin/src/cli/templates/bensdk-viewer/src/app.html +9 -9
- package/bin/src/cli/templates/bensdk-viewer/src/routes/+page.svelte +2 -20
- package/bin/src/cli/templates/bensdk-viewer/startup.ts +4 -5
- package/bin/src/cli/templates/bensdk-viewer/svelte.config.js +9 -9
- package/bin/src/cli/templates/bensdk-viewer/tsconfig.json +17 -17
- package/bin/src/cli/templates/bensdk-viewer/vite.config.ts +2 -4
- package/bin/src/cli/utils/zip.js +2 -2
- package/bin/src/cli/utils/zip.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -22,9 +22,9 @@ O BenSDK é um framework para a criação de integrações entre benefícios e o
|
|
|
22
22
|
- 🚀 Geração de projetos benApp
|
|
23
23
|
- ⚡ Configuração automática do ambiente de desenvolvimento
|
|
24
24
|
- 📦 Suporte a TypeScript
|
|
25
|
-
- 🎯 Interface de linha de comando
|
|
25
|
+
- 🎯 Interface de linha de comando
|
|
26
26
|
|
|
27
|
-
## 🛠️ Instalação Local
|
|
27
|
+
## 🛠️ Instalação Local
|
|
28
28
|
|
|
29
29
|
Como o projeto ainda está em fase de testes internos, você precisará clonar o repositório:
|
|
30
30
|
|
|
@@ -34,7 +34,6 @@ cd bensdk-cli
|
|
|
34
34
|
npm install
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
|
|
38
37
|
## 🚀 Uso
|
|
39
38
|
|
|
40
39
|
Para criar um novo projeto benApp:
|
|
@@ -62,7 +61,7 @@ O projeto gerado inclui:
|
|
|
62
61
|
- ⚙️ Configuração TypeScript
|
|
63
62
|
- 📦 Estrutura básica para criação do módulo
|
|
64
63
|
- 📚 Dependências necessárias
|
|
65
|
-
- 🖼️ Simulador do Integrador para desenvolvimento local
|
|
64
|
+
- 🖼️ Simulador do Integrador para desenvolvimento local
|
|
66
65
|
- 🔄 Geração automática de handlers baseado na máquina de estado
|
|
67
66
|
|
|
68
67
|
## 📦 Dependências
|
package/bin/src/cli/app.js
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import chalk from 'chalk';
|
|
2
3
|
import { Command } from 'commander';
|
|
4
|
+
import dotenv from 'dotenv';
|
|
5
|
+
import fs from 'fs';
|
|
3
6
|
import init from './init.js';
|
|
4
7
|
import { zipFolder } from './utils/zip.js';
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
import dotenv from 'dotenv';
|
|
7
|
-
import chalk from 'chalk';
|
|
8
8
|
const program = new Command();
|
|
9
|
+
program.name('BenSDK Tool').description('CLI to create benefits integration').version('0.0.1');
|
|
9
10
|
program
|
|
10
|
-
.
|
|
11
|
-
.description('CLI to create benefits integration')
|
|
12
|
-
.version('0.0.1');
|
|
13
|
-
program.command('init')
|
|
11
|
+
.command('init')
|
|
14
12
|
.description('New project')
|
|
15
13
|
.argument('<string>', 'Benefit ID')
|
|
16
14
|
.action((benefitID, options) => {
|
|
17
15
|
init(benefitID);
|
|
18
16
|
});
|
|
19
|
-
program
|
|
17
|
+
program
|
|
18
|
+
.command('deploy')
|
|
20
19
|
.description('Deploy benSDK project')
|
|
21
20
|
.option('-p, --path <type>', 'App directory')
|
|
22
21
|
.action((data, opt) => {
|
package/bin/src/cli/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/cli/app.ts"],"names":[],"mappings":";AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/cli/app.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,WAAW,CAAC,oCAAoC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/F,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,aAAa,CAAC;KAC1B,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;KAClC,MAAM,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE;IAC7B,IAAI,CAAC,SAAS,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,uBAAuB,CAAC;KACpC,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC;KAC5C,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IACpB,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;IAChD,MAAM,YAAY,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,OAAO,UAAU,EAAE,MAAM,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC,CAAC;QAC/E,OAAO,CAAC,IAAI,EAAE,CAAC;IACjB,CAAC;IACD,MAAM,SAAS,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC;IAChD,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/bin/src/cli/init.js
CHANGED
|
@@ -1,46 +1,58 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { exec } from 'child_process';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import ora from 'ora';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import packageTemplate from './templates/package.template.json' with { type: 'json' };
|
|
10
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
11
|
const __dirname = path.dirname(__filename);
|
|
12
|
-
const templatesDir = path.join(__dirname,
|
|
13
|
-
const benefitDefinitionTemplate = fs.readFileSync(path.join(templatesDir,
|
|
14
|
-
const benefitDefinitionTypesTemplate = fs.readFileSync(path.join(templatesDir,
|
|
15
|
-
const staticFiles = fs.readdirSync(path.join(templatesDir,
|
|
12
|
+
const templatesDir = path.join(__dirname, 'templates');
|
|
13
|
+
const benefitDefinitionTemplate = fs.readFileSync(path.join(templatesDir, 'benefit-definition.template.ts'), 'utf-8');
|
|
14
|
+
const benefitDefinitionTypesTemplate = fs.readFileSync(path.join(templatesDir, 'benefit-definition.types.template.ts'), 'utf-8');
|
|
15
|
+
const staticFiles = fs.readdirSync(path.join(templatesDir, 'bensdk-base'));
|
|
16
16
|
export default async function (benefitID) {
|
|
17
|
-
const availableActions = [
|
|
17
|
+
const availableActions = ['GRANT', 'REVOKE'];
|
|
18
18
|
if (!benefitID) {
|
|
19
|
-
console.error(
|
|
19
|
+
console.error('Benefit ID is required');
|
|
20
20
|
process.exit(1);
|
|
21
21
|
}
|
|
22
22
|
const { customAvailableActions } = await inquirer.prompt({
|
|
23
|
-
type:
|
|
24
|
-
name:
|
|
25
|
-
message:
|
|
26
|
-
choices: [
|
|
23
|
+
type: 'checkbox',
|
|
24
|
+
name: 'customAvailableActions',
|
|
25
|
+
message: 'Select the available actions',
|
|
26
|
+
choices: ['RECHARGE', 'DEDUCTION', 'GRANT_DEPENDENT', 'REVOKE_DEPENDENT']
|
|
27
27
|
});
|
|
28
28
|
const spinner = ora('Creating project').start();
|
|
29
29
|
let actions = [...availableActions, ...customAvailableActions].map((action) => `"${action}"`);
|
|
30
30
|
packageTemplate.name = benefitID;
|
|
31
|
-
let benefitDefinition = benefitDefinitionTemplate.replace(/benefitID:
|
|
32
|
-
benefitDefinition = benefitDefinition.replace(/availableActions: \[\].*/, `availableActions: [${actions.join(
|
|
31
|
+
let benefitDefinition = benefitDefinitionTemplate.replace(/benefitID: '.*'/, `benefitID: "${benefitID.toUpperCase()}"`);
|
|
32
|
+
benefitDefinition = benefitDefinition.replace(/availableActions: \[\].*/, `availableActions: [${actions.join(', ')}],`);
|
|
33
33
|
let benefitDefinitionTypes = benefitDefinitionTypesTemplate;
|
|
34
|
-
if (!customAvailableActions.includes(
|
|
35
|
-
benefitDefinition = benefitDefinition.replace(/\/\*\* <recharge> \*\/[\s\S]*?\/\*\* <\/recharge> \*\//g,
|
|
36
|
-
benefitDefinitionTypes = benefitDefinitionTypes.replace(/\/\*\* <recharge> \*\/[\s\S]*?\/\*\* <\/recharge> \*\//g,
|
|
34
|
+
if (!customAvailableActions.includes('RECHARGE')) {
|
|
35
|
+
benefitDefinition = benefitDefinition.replace(/\/\*\* <recharge> \*\/[\s\S]*?\/\*\* <\/recharge> \*\//g, '');
|
|
36
|
+
benefitDefinitionTypes = benefitDefinitionTypes.replace(/\/\*\* <recharge> \*\/[\s\S]*?\/\*\* <\/recharge> \*\//g, '');
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
39
|
// If RECHARGE is selected, just remove the recharge comment markers
|
|
40
|
-
benefitDefinition = benefitDefinition.replace(/\/\*\* <recharge> \*\/\n?/g,
|
|
41
|
-
benefitDefinition = benefitDefinition.replace(/\/\*\* <\/recharge> \*\/\n?/g,
|
|
42
|
-
benefitDefinitionTypes = benefitDefinitionTypes.replace(/\/\*\* <recharge> \*\/\n?/g,
|
|
43
|
-
benefitDefinitionTypes = benefitDefinitionTypes.replace(/\/\*\* <\/recharge> \*\/\n?/g,
|
|
40
|
+
benefitDefinition = benefitDefinition.replace(/\/\*\* <recharge> \*\/\n?/g, '');
|
|
41
|
+
benefitDefinition = benefitDefinition.replace(/\/\*\* <\/recharge> \*\/\n?/g, '');
|
|
42
|
+
benefitDefinitionTypes = benefitDefinitionTypes.replace(/\/\*\* <recharge> \*\/\n?/g, '');
|
|
43
|
+
benefitDefinitionTypes = benefitDefinitionTypes.replace(/\/\*\* <\/recharge> \*\/\n?/g, '');
|
|
44
|
+
}
|
|
45
|
+
if (!customAvailableActions.includes('GRANT_DEPENDENT') &&
|
|
46
|
+
!customAvailableActions.includes('REVOKE_DEPENDENT')) {
|
|
47
|
+
benefitDefinition = benefitDefinition.replace(/\/\*\* <dependent> \*\/[\s\S]*?\/\*\* <\/dependent> \*\//g, '');
|
|
48
|
+
benefitDefinitionTypes = benefitDefinitionTypes.replace(/\/\*\* <dependent> \*\/[\s\S]*?\/\*\* <\/dependent> \*\//g, '');
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// If RECHARGE is selected, just remove the recharge comment markers
|
|
52
|
+
benefitDefinition = benefitDefinition.replace(/\/\*\* <dependent> \*\/\n?/g, '');
|
|
53
|
+
benefitDefinition = benefitDefinition.replace(/\/\*\* <\/dependent> \*\/\n?/g, '');
|
|
54
|
+
benefitDefinitionTypes = benefitDefinitionTypes.replace(/\/\*\* <dependent> \*\/\n?/g, '');
|
|
55
|
+
benefitDefinitionTypes = benefitDefinitionTypes.replace(/\/\*\* <\/dependent> \*\/\n?/g, '');
|
|
44
56
|
}
|
|
45
57
|
const currentDirectory = process.cwd();
|
|
46
58
|
const appDirectory = `${currentDirectory}/${benefitID}`;
|
|
@@ -48,20 +60,24 @@ export default async function (benefitID) {
|
|
|
48
60
|
fs.writeFileSync(`${appDirectory}/src/benefit-definition.ts`, benefitDefinition);
|
|
49
61
|
fs.writeFileSync(`${appDirectory}/src/benefit-definition.types.ts`, benefitDefinitionTypes);
|
|
50
62
|
fs.mkdirSync(`${appDirectory}/src/lib`, { recursive: true });
|
|
51
|
-
fs.cpSync(path.join(templatesDir,
|
|
63
|
+
fs.cpSync(path.join(templatesDir, 'bensdk-lib'), `${appDirectory}/src/lib`, { recursive: true });
|
|
52
64
|
fs.mkdirSync(`${appDirectory}/bin/server`, { recursive: true });
|
|
53
|
-
fs.cpSync(path.join(templatesDir,
|
|
65
|
+
fs.cpSync(path.join(templatesDir, 'bensdk-local-server'), `${appDirectory}/bin/server`, {
|
|
66
|
+
recursive: true
|
|
67
|
+
});
|
|
54
68
|
fs.mkdirSync(`${appDirectory}/bin/viewer`, { recursive: true });
|
|
55
|
-
fs.cpSync(path.join(templatesDir,
|
|
69
|
+
fs.cpSync(path.join(templatesDir, 'bensdk-viewer'), `${appDirectory}/bin/viewer`, {
|
|
70
|
+
recursive: true
|
|
71
|
+
});
|
|
56
72
|
fs.mkdirSync(`${appDirectory}/bin/cli`, { recursive: true });
|
|
57
|
-
fs.cpSync(path.join(templatesDir,
|
|
73
|
+
fs.cpSync(path.join(templatesDir, 'bensdk-cli'), `${appDirectory}/bin/cli`, { recursive: true });
|
|
58
74
|
staticFiles.forEach((item) => {
|
|
59
|
-
fs.writeFileSync(`${appDirectory}/${item.split(
|
|
75
|
+
fs.writeFileSync(`${appDirectory}/${item.split('.template')[0]}`, fs.readFileSync(path.join(templatesDir, 'bensdk-base', item), 'utf-8'));
|
|
60
76
|
});
|
|
61
77
|
spinner.stop();
|
|
62
78
|
fs.writeFileSync(`${appDirectory}/package.json`, JSON.stringify(packageTemplate, null, 4));
|
|
63
79
|
console.log(chalk.green('✔ Project created'));
|
|
64
|
-
spinner.text =
|
|
80
|
+
spinner.text = 'Building benSDK app';
|
|
65
81
|
spinner.start();
|
|
66
82
|
exec(`cd ${appDirectory} && npm install > /dev/null && npm run format > /dev/null && cd bin/viewer && npx vite build > /dev/null`, (error, stdout, stderr) => {
|
|
67
83
|
if (error || stderr) {
|
package/bin/src/cli/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ const benefitDefinition = {
|
|
|
4
4
|
/**
|
|
5
5
|
* ID do benefício, deve ser declarado em UPPERCASE
|
|
6
6
|
*/
|
|
7
|
-
benefitID:
|
|
7
|
+
benefitID: '',
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Actions disponíveis:
|
|
@@ -12,6 +12,8 @@ const benefitDefinition = {
|
|
|
12
12
|
* - REVOKE: revogação de benefício (obrigatório)
|
|
13
13
|
* - RECHARGE: recarga de benefício (opcional)
|
|
14
14
|
* - DEDUCTION: desconto em folha de benefício (opcional). DEDUCTION não precisa ser implementado.
|
|
15
|
+
* - GRANT_DEPENDENT: concessão de benefício para dependente (opcional).
|
|
16
|
+
* - REVOKE_DEPENDENT: revogação de benefício para dependente (opcional).
|
|
15
17
|
*/
|
|
16
18
|
availableActions: [],
|
|
17
19
|
|
|
@@ -74,8 +76,37 @@ const benefitDefinition = {
|
|
|
74
76
|
next: 'RECHARGE_SUCCEEDED',
|
|
75
77
|
fail: 'RECHARGE_FAILED'
|
|
76
78
|
}
|
|
77
|
-
}
|
|
79
|
+
},
|
|
78
80
|
/** </recharge> */
|
|
81
|
+
|
|
82
|
+
/** <dependent> */
|
|
83
|
+
/**
|
|
84
|
+
* O stateMachine do tipo GRANT_DEPENDENT sempre inicia em REQUESTED_GRANT_DEPENDENT e finaliza em GRANTED_DEPENDENT ou FAILED_TO_GRANT_DEPENDENT
|
|
85
|
+
*/
|
|
86
|
+
GRANT_DEPENDENT: {
|
|
87
|
+
REQUESTED_GRANT_DEPENDENT: {
|
|
88
|
+
next: 'REQUEST_CREATE_DEPENDENT'
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
REQUEST_CREATE_DEPENDENT: {
|
|
92
|
+
next: 'GRANTED_DEPENDENT',
|
|
93
|
+
fail: 'FAILED_TO_GRANT_DEPENDENT'
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
/**
|
|
97
|
+
* O stateMachine do tipo REVOKE_DEPENDENT sempre inicia em REQUESTED_REVOKE_DEPENDENT e finaliza em REVOKED_DEPENDENT ou FAILED_TO_REVOKE_DEPENDENT
|
|
98
|
+
*/
|
|
99
|
+
REVOKE_DEPENDENT: {
|
|
100
|
+
REQUESTED_REVOKE_DEPENDENT: {
|
|
101
|
+
next: 'REQUEST_REMOVE_DEPENDENT'
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
REQUEST_REMOVE_DEPENDENT: {
|
|
105
|
+
next: 'REVOKED_DEPENDENT',
|
|
106
|
+
fail: 'FAILED_TO_REVOKE_DEPENDENT'
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** </dependent> */
|
|
79
110
|
},
|
|
80
111
|
|
|
81
112
|
/**
|
|
@@ -92,6 +123,9 @@ const benefitDefinition = {
|
|
|
92
123
|
*/
|
|
93
124
|
eligibilityOptions: {
|
|
94
125
|
GRANT: z.object({}),
|
|
126
|
+
/** <dependent> */
|
|
127
|
+
GRANT_DEPENDENT: z.object({}),
|
|
128
|
+
/** </dependent> */
|
|
95
129
|
/** <recharge> */
|
|
96
130
|
RECHARGE: z.object({})
|
|
97
131
|
/** </recharge> */
|
|
@@ -110,6 +144,18 @@ const benefitDefinition = {
|
|
|
110
144
|
SYNC_EXISTING_REVOKE: z.object({}),
|
|
111
145
|
REQUEST_REMOVE_EMPLOYEE: z.object({})
|
|
112
146
|
}),
|
|
147
|
+
|
|
148
|
+
/** <dependent> */
|
|
149
|
+
GRANT_DEPENDENT: z.object({
|
|
150
|
+
REQUESTED_GRANT_DEPENDENT: z.object({}),
|
|
151
|
+
REQUEST_CREATE_DEPENDENT: z.object({})
|
|
152
|
+
}),
|
|
153
|
+
REVOKE_DEPENDENT: z.object({
|
|
154
|
+
REQUESTED_REVOKE_DEPENDENT: z.object({}),
|
|
155
|
+
REQUEST_REMOVE_DEPENDENT: z.object({})
|
|
156
|
+
}),
|
|
157
|
+
/** </dependent> */
|
|
158
|
+
|
|
113
159
|
/** <recharge> */
|
|
114
160
|
RECHARGE: z.object({
|
|
115
161
|
REQUESTED_RECHARGE: z.object({}),
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { ActionBaseGrantRevoke, ActionBaseRecharge } from './lib/types/action.types';
|
|
2
1
|
import z from 'zod';
|
|
3
2
|
import benefitDefinition from './benefit-definition';
|
|
3
|
+
import {
|
|
4
|
+
ActionBaseDependent,
|
|
5
|
+
ActionBaseGrantRevoke,
|
|
6
|
+
ActionBaseRecharge
|
|
7
|
+
} from './lib/types/action.types';
|
|
4
8
|
|
|
5
9
|
type ActionEligibilityOptionsGrant = z.infer<
|
|
6
10
|
typeof benefitDefinition.actions.eligibilityOptions.GRANT
|
|
@@ -10,6 +14,11 @@ type ActionEligibilityOptionsRecharge = z.infer<
|
|
|
10
14
|
typeof benefitDefinition.actions.eligibilityOptions.RECHARGE
|
|
11
15
|
>;
|
|
12
16
|
/** </recharge> */
|
|
17
|
+
/** <dependent> */
|
|
18
|
+
type ActionEligibilityOptionsDependent = z.infer<
|
|
19
|
+
typeof benefitDefinition.actions.eligibilityOptions.GRANT_DEPENDENT
|
|
20
|
+
>;
|
|
21
|
+
/** </dependent> */
|
|
13
22
|
export type ActionCtx = z.infer<typeof benefitDefinition.actions.ctx>;
|
|
14
23
|
|
|
15
24
|
export type ActionLogGrant = z.infer<typeof benefitDefinition.actions.log.GRANT>;
|
|
@@ -18,6 +27,12 @@ export type ActionLogRevoke = z.infer<typeof benefitDefinition.actions.log.REVOK
|
|
|
18
27
|
/** <recharge> */
|
|
19
28
|
export type ActionLogRecharge = z.infer<typeof benefitDefinition.actions.log.RECHARGE>;
|
|
20
29
|
/** </recharge> */
|
|
30
|
+
/** <dependent> */
|
|
31
|
+
export type ActionLogGrantDependent = z.infer<typeof benefitDefinition.actions.log.GRANT_DEPENDENT>;
|
|
32
|
+
export type ActionLogRevokeDependent = z.infer<
|
|
33
|
+
typeof benefitDefinition.actions.log.REVOKE_DEPENDENT
|
|
34
|
+
>;
|
|
35
|
+
/** </dependent> */
|
|
21
36
|
export type ActionGrant = ActionBaseGrantRevoke & {
|
|
22
37
|
ctx: ActionCtx;
|
|
23
38
|
eligibilityOptions: ActionEligibilityOptionsGrant;
|
|
@@ -29,6 +44,7 @@ export type ActionRevoke = ActionBaseGrantRevoke & {
|
|
|
29
44
|
eligibilityOptions: ActionEligibilityOptionsGrant;
|
|
30
45
|
logs: ActionLogRevoke;
|
|
31
46
|
};
|
|
47
|
+
|
|
32
48
|
/** <recharge> */
|
|
33
49
|
export type ActionRecharge = ActionBaseRecharge & {
|
|
34
50
|
ctx: ActionCtx;
|
|
@@ -36,3 +52,15 @@ export type ActionRecharge = ActionBaseRecharge & {
|
|
|
36
52
|
logs: ActionLogRecharge;
|
|
37
53
|
};
|
|
38
54
|
/** </recharge> */
|
|
55
|
+
/** <dependent> */
|
|
56
|
+
export type ActionGrantDependent = ActionBaseDependent & {
|
|
57
|
+
ctx: ActionCtx;
|
|
58
|
+
eligibilityOptions: ActionEligibilityOptionsDependent;
|
|
59
|
+
logs: ActionLogGrantDependent;
|
|
60
|
+
};
|
|
61
|
+
export type ActionRevokeDependent = ActionBaseDependent & {
|
|
62
|
+
ctx: ActionCtx;
|
|
63
|
+
eligibilityOptions: ActionEligibilityOptionsDependent;
|
|
64
|
+
logs: ActionLogRevokeDependent;
|
|
65
|
+
};
|
|
66
|
+
/** </dependent> */
|
|
@@ -1,57 +1,61 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { initialStates } from './lib/state-machine';
|
|
3
|
+
import { validateBenefitDefinition } from './validate';
|
|
4
4
|
|
|
5
5
|
async function main() {
|
|
6
|
-
const benefitDefinition = (await import(`${process.cwd()}/src/benefit-definition.ts`
|
|
7
|
-
.default;
|
|
6
|
+
const benefitDefinition = (await import(`${process.cwd()}/src/benefit-definition.ts`)).default;
|
|
8
7
|
|
|
9
8
|
await validateBenefitDefinition(benefitDefinition);
|
|
10
9
|
|
|
11
10
|
// Read the state handler template
|
|
12
11
|
const stateHandlerTemplate = fs.readFileSync(
|
|
13
|
-
process.cwd() +
|
|
14
|
-
|
|
12
|
+
process.cwd() + '/bin/cli/templates/state.handler.template.ts',
|
|
13
|
+
'utf-8'
|
|
15
14
|
);
|
|
16
15
|
|
|
17
|
-
|
|
18
16
|
// Get all state machines and their states
|
|
19
17
|
const stateMachines = Object.entries(benefitDefinition.stateMachine)
|
|
20
18
|
.filter(([action]) => benefitDefinition.availableActions.includes(action))
|
|
21
|
-
.reduce(
|
|
22
|
-
acc[action
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
.reduce(
|
|
20
|
+
(acc, [action, states]) => {
|
|
21
|
+
acc[action] = Object.keys(states as object);
|
|
22
|
+
return acc;
|
|
23
|
+
},
|
|
24
|
+
{} as Record<string, string[]>
|
|
25
|
+
);
|
|
25
26
|
|
|
26
27
|
Object.keys(stateMachines).forEach((action) => {
|
|
27
28
|
const states = stateMachines[action];
|
|
28
|
-
|
|
29
|
+
|
|
29
30
|
states.forEach((state) => {
|
|
30
|
-
if(initialStates.includes(state)){
|
|
31
|
-
return
|
|
31
|
+
if (initialStates.includes(state)) {
|
|
32
|
+
return;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
const fileName = `${state.toLocaleLowerCase()}.handler.ts`;
|
|
35
36
|
let stateHandler = stateHandlerTemplate;
|
|
36
|
-
const actionInCamelCase =
|
|
37
|
-
|
|
37
|
+
const actionInCamelCase = action
|
|
38
|
+
.split('_')
|
|
39
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
40
|
+
.join('');
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
`const stateMachine = benefitDefinition.stateMachine.${action}.${state}; `
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
stateHandler = stateHandler.replace(
|
|
46
|
-
"// import {Action} ",
|
|
47
|
-
`import { ActionCtx, Action${actionInCamelCase}, ActionLog${actionInCamelCase} } `
|
|
42
|
+
stateHandler = stateHandler.replace(
|
|
43
|
+
'// StateMachine,',
|
|
44
|
+
`const stateMachine = benefitDefinition.stateMachine.${action}.${state}; `
|
|
48
45
|
);
|
|
49
46
|
|
|
50
47
|
stateHandler = stateHandler.replace(
|
|
51
|
-
|
|
52
|
-
`
|
|
48
|
+
`// import benefitDefinition from '../benefit-definition';`,
|
|
49
|
+
`import benefitDefinition from '../benefit-definition';`
|
|
53
50
|
);
|
|
54
51
|
|
|
52
|
+
stateHandler = stateHandler.replace(
|
|
53
|
+
'// import {Action}',
|
|
54
|
+
`import { ActionCtx, Action${actionInCamelCase}, ActionLog${actionInCamelCase} } `
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
stateHandler = stateHandler.replace('// Action,', `Action${actionInCamelCase},`);
|
|
58
|
+
|
|
55
59
|
stateHandler = stateHandler.replace(
|
|
56
60
|
'// ActionLog[""],',
|
|
57
61
|
`ActionLog${actionInCamelCase}["${state}"],`
|
|
@@ -61,7 +65,7 @@ async function main() {
|
|
|
61
65
|
if (!fs.existsSync(handlersDir)) {
|
|
62
66
|
fs.mkdirSync(handlersDir, { recursive: true });
|
|
63
67
|
}
|
|
64
|
-
fs.writeFileSync(`${handlersDir}/${fileName}`, stateHandler,
|
|
68
|
+
fs.writeFileSync(`${handlersDir}/${fileName}`, stateHandler, 'utf-8');
|
|
65
69
|
});
|
|
66
70
|
});
|
|
67
71
|
}
|
|
@@ -3,7 +3,9 @@ import z from 'zod';
|
|
|
3
3
|
export const BenefitDefinitionSchema = z
|
|
4
4
|
.object({
|
|
5
5
|
benefitID: z.string().min(3),
|
|
6
|
-
availableActions: z.array(
|
|
6
|
+
availableActions: z.array(
|
|
7
|
+
z.enum(['GRANT', 'REVOKE', 'RECHARGE', 'DEDUCTION', 'GRANT_DEPENDENT', 'REVOKE_DEPENDENT'])
|
|
8
|
+
),
|
|
7
9
|
|
|
8
10
|
stateMachine: z.object({
|
|
9
11
|
GRANT: z
|
|
@@ -22,6 +24,18 @@ export const BenefitDefinitionSchema = z
|
|
|
22
24
|
})
|
|
23
25
|
.passthrough()
|
|
24
26
|
.optional(),
|
|
27
|
+
GRANT_DEPENDENT: z
|
|
28
|
+
.object({
|
|
29
|
+
REQUESTED_GRANT_DEPENDENT: z.object({ next: z.string() })
|
|
30
|
+
})
|
|
31
|
+
.passthrough()
|
|
32
|
+
.optional(),
|
|
33
|
+
REVOKE_DEPENDENT: z
|
|
34
|
+
.object({
|
|
35
|
+
REQUESTED_REVOKE_DEPENDENT: z.object({ next: z.string() })
|
|
36
|
+
})
|
|
37
|
+
.passthrough()
|
|
38
|
+
.optional(),
|
|
25
39
|
DEDUCTION: z
|
|
26
40
|
.object({
|
|
27
41
|
REQUESTED_DEDUCTION: z.object({ next: z.string() })
|
|
@@ -33,7 +47,8 @@ export const BenefitDefinitionSchema = z
|
|
|
33
47
|
actions: z.object({
|
|
34
48
|
eligibilityOptions: z.object({
|
|
35
49
|
GRANT: z.object({}).passthrough(),
|
|
36
|
-
RECHARGE: z.object({}).passthrough().optional()
|
|
50
|
+
RECHARGE: z.object({}).passthrough().optional(),
|
|
51
|
+
GRANT_DEPENDENT: z.object({}).passthrough().optional()
|
|
37
52
|
}),
|
|
38
53
|
|
|
39
54
|
ctx: z.object({}).passthrough(),
|
|
@@ -42,7 +57,9 @@ export const BenefitDefinitionSchema = z
|
|
|
42
57
|
GRANT: z.object({}).passthrough(),
|
|
43
58
|
REVOKE: z.object({}).passthrough(),
|
|
44
59
|
RECHARGE: z.object({}).passthrough().optional(),
|
|
45
|
-
DEDUCTION: z.object({}).passthrough().optional()
|
|
60
|
+
DEDUCTION: z.object({}).passthrough().optional(),
|
|
61
|
+
GRANT_DEPENDENT: z.object({}).passthrough().optional(),
|
|
62
|
+
REVOKE_DEPENDENT: z.object({}).passthrough().optional()
|
|
46
63
|
})
|
|
47
64
|
})
|
|
48
65
|
})
|
|
@@ -1,65 +1,70 @@
|
|
|
1
1
|
export class InvalidTransitionError extends Error {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
}
|
|
2
|
+
constructor(transition: string, state: string) {
|
|
3
|
+
super(`Invalid transition ${transition} from state ${state}`);
|
|
5
4
|
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type StateTransitionActions = 'next' | 'fail' | 'skip' | 'update' | 'purge';
|
|
8
|
+
|
|
9
|
+
type State = {
|
|
10
|
+
[key in StateTransitionActions]?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type States = {
|
|
14
|
+
[key: string]: State;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const initialStates = [
|
|
18
|
+
'REQUESTED_GRANT',
|
|
19
|
+
'REQUESTED_REVOKE',
|
|
20
|
+
'REQUESTED_RECHARGE',
|
|
21
|
+
'REQUESTED_DEDUCTION',
|
|
22
|
+
'REQUESTED_GRANT_DEPENDENT',
|
|
23
|
+
'REQUESTED_REVOKE_DEPENDENT'
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export const finalStates = [
|
|
27
|
+
'GRANTED',
|
|
28
|
+
'FAILED_TO_GRANT',
|
|
29
|
+
'REVOKED',
|
|
30
|
+
'FAILED_TO_REVOKE',
|
|
31
|
+
'RECHARGE_SUCCEEDED',
|
|
32
|
+
'RECHARGE_FAILED',
|
|
33
|
+
'DEDUCTION_SUCCEEDED',
|
|
34
|
+
'DEDUCTION_FAILED',
|
|
35
|
+
'GRANTED_DEPENDENT',
|
|
36
|
+
'FAILED_TO_GRANT_DEPENDENT',
|
|
37
|
+
'REVOKED_DEPENDENT',
|
|
38
|
+
'FAILED_TO_REVOKE_DEPENDENT'
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Creates a state machine, validating the transitions
|
|
43
|
+
* @param {States} states - The state machine states
|
|
44
|
+
* @throws {InvalidTransitionError} If an invalid transition is found
|
|
45
|
+
* @returns {States} The state machine
|
|
46
|
+
*/
|
|
47
|
+
export default function validateStateMachine<S extends States>(states: S): S {
|
|
48
|
+
const stateKeys = Object.keys(states);
|
|
49
|
+
|
|
50
|
+
for (const stateKey of stateKeys) {
|
|
51
|
+
const state = states[stateKey];
|
|
52
|
+
|
|
53
|
+
const stateTransitions = Object.keys(state);
|
|
54
|
+
|
|
55
|
+
for (const transition of stateTransitions) {
|
|
56
|
+
// Validate if transition is present in the states
|
|
57
|
+
const nextState = state[transition as StateTransitionActions];
|
|
58
|
+
if (
|
|
59
|
+
nextState !== undefined &&
|
|
60
|
+
!stateKeys.includes(nextState) &&
|
|
61
|
+
!initialStates.includes(nextState) &&
|
|
62
|
+
!finalStates.includes(nextState)
|
|
63
|
+
) {
|
|
64
|
+
throw new InvalidTransitionError(transition, stateKey);
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
|
-
|
|
63
|
-
return states;
|
|
64
67
|
}
|
|
65
|
-
|
|
68
|
+
|
|
69
|
+
return states;
|
|
70
|
+
}
|