@velocitycareerlabs/data-loader 1.20.0-dev-build.1cb592b8f → 1.20.0-dev-build.1e6832e17
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/package.json +3 -2
- package/src/batch-issuing/constants.js +25 -0
- package/src/batch-issuing/file-writers.js +2 -5
- package/src/batch-issuing/index.js +50 -48
- package/src/batch-issuing/orchestrators.js +146 -99
- package/src/batch-issuing/prepare-data.js +40 -81
- package/src/batch-issuing/validate-directory-exists.js +3 -3
- package/src/helpers/index.js +2 -0
- package/src/helpers/load-csv.js +14 -11
- package/src/helpers/parse-column.js +8 -0
- package/src/helpers/prepare-variable-sets.js +23 -0
- package/src/vendor-credentials/README.md +48 -8
- package/src/vendor-credentials/index.js +10 -14
- package/src/vendor-credentials/orchestrator.js +22 -0
- package/src/vendor-credentials/prepare-data.js +5 -9
- package/test/batch-issuing.test.js +448 -75
- package/test/data/batch-vars-offerids.csv +3 -3
- package/test/data/email-offer.template.json +1 -1
- package/test/vendor-credentials.test.js +6 -4
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@velocitycareerlabs/data-loader",
|
3
|
-
"version": "1.20.0-dev-build.
|
3
|
+
"version": "1.20.0-dev-build.1e6832e17",
|
4
4
|
"description": "A tool for uploading data to the different target systems.",
|
5
5
|
"repository": "https://github.com/velocitycareerlabs/packages",
|
6
6
|
"main": "src/index.js",
|
@@ -26,6 +26,7 @@
|
|
26
26
|
"eslint-plugin-prettier": "^4.2.1",
|
27
27
|
"eslint-watch": "^7.0.0",
|
28
28
|
"jest": "29.6.2",
|
29
|
+
"nock": "^13.2.9",
|
29
30
|
"prettier": "^2.2.1"
|
30
31
|
},
|
31
32
|
"dependencies": {
|
@@ -39,5 +40,5 @@
|
|
39
40
|
"lodash": "~4.17.20",
|
40
41
|
"nanoid": "3.3.1"
|
41
42
|
},
|
42
|
-
"gitHead": "
|
43
|
+
"gitHead": "f137575a659703ef89f3cd454989c46d0e0dc231"
|
43
44
|
}
|
@@ -3,6 +3,31 @@ const DisclosureType = {
|
|
3
3
|
EXISTING: 'existing',
|
4
4
|
};
|
5
5
|
|
6
|
+
const CREDENTIAL_TYPES = {
|
7
|
+
EMAIL: 'EmailV1.0',
|
8
|
+
PHONE: 'PhoneV1.0',
|
9
|
+
DRIVER_LICENSE: 'DriversLicenseV1.0',
|
10
|
+
ID_DOCUMENT: 'IdDocumentV1.0',
|
11
|
+
NATIONAL_ID_CARD: 'NationalIdCardV1.0',
|
12
|
+
PASSPORT: 'PassportV1.0',
|
13
|
+
PROOF_OF_AGE: 'ProofOfAgeV1.0',
|
14
|
+
RESIDENT_PERMIT: 'ResidentPermitV1.0',
|
15
|
+
};
|
16
|
+
const DEFAULT_ID_DOCUMENT_CREDENTIALS_PATH =
|
17
|
+
'$.idDocumentCredentials[*].credentialSubject.identifier';
|
18
|
+
const idCredentialTypeToPick = {
|
19
|
+
[CREDENTIAL_TYPES.EMAIL]: '$.emails',
|
20
|
+
[CREDENTIAL_TYPES.PHONE]: '$.phones',
|
21
|
+
[CREDENTIAL_TYPES.DRIVER_LICENSE]: DEFAULT_ID_DOCUMENT_CREDENTIALS_PATH,
|
22
|
+
[CREDENTIAL_TYPES.ID_DOCUMENT]: DEFAULT_ID_DOCUMENT_CREDENTIALS_PATH,
|
23
|
+
[CREDENTIAL_TYPES.NATIONAL_ID_CARD]: DEFAULT_ID_DOCUMENT_CREDENTIALS_PATH,
|
24
|
+
[CREDENTIAL_TYPES.PASSPORT]: DEFAULT_ID_DOCUMENT_CREDENTIALS_PATH,
|
25
|
+
[CREDENTIAL_TYPES.PROOF_OF_AGE]: DEFAULT_ID_DOCUMENT_CREDENTIALS_PATH,
|
26
|
+
[CREDENTIAL_TYPES.RESIDENT_PERMIT]: DEFAULT_ID_DOCUMENT_CREDENTIALS_PATH,
|
27
|
+
};
|
28
|
+
|
6
29
|
module.exports = {
|
7
30
|
DisclosureType,
|
31
|
+
CREDENTIAL_TYPES,
|
32
|
+
idCredentialTypeToPick,
|
8
33
|
};
|
@@ -18,14 +18,11 @@ const writeJsonFile = async (obj, jsonName, { path }) => {
|
|
18
18
|
return { fileName, filePath };
|
19
19
|
};
|
20
20
|
|
21
|
-
const writeOutputCsv = (
|
22
|
-
data,
|
23
|
-
{ path, outputCsvName = 'output', vendorUserIdName = 'email' }
|
24
|
-
) => {
|
21
|
+
const writeOutputCsv = (data, { path, outputCsvName, vendorUserIdColName }) => {
|
25
22
|
const fileName = `${outputCsvName}.csv`;
|
26
23
|
const filePath = join(path, fileName);
|
27
24
|
const buff = fs.createWriteStream(filePath, {});
|
28
|
-
buff.write([
|
25
|
+
buff.write([vendorUserIdColName, ...OUTPUT_CSV_HEADERS].join(','));
|
29
26
|
for (const { vendorUserId, deeplink, qrcodeFilePath } of data) {
|
30
27
|
buff.write(`\n${vendorUserId},${deeplink},${qrcodeFilePath}`);
|
31
28
|
}
|
@@ -1,79 +1,60 @@
|
|
1
1
|
const { program } = require('commander');
|
2
2
|
const { reduce } = require('lodash/fp');
|
3
|
-
const { printInfo, printError } = require('../helpers
|
3
|
+
const { printInfo, printError, parseColumn } = require('../helpers');
|
4
4
|
const { runBatchIssuing } = require('./orchestrators');
|
5
5
|
|
6
|
-
const parseVar = reduce((acc, pair) => {
|
7
|
-
const [key, value] = pair.split('=');
|
8
|
-
acc[key] = value;
|
9
|
-
return acc;
|
10
|
-
}, {});
|
11
|
-
|
12
|
-
const validateOptions = (options) => {
|
13
|
-
if (options.dryrun == null && options.endpoint == null) {
|
14
|
-
throw new Error(
|
15
|
-
'"-e" or "--endpoint" is required unless executing a "dryrun"'
|
16
|
-
);
|
17
|
-
}
|
18
|
-
if (options.endpoint != null && options.authToken == null) {
|
19
|
-
throw new Error('"-a" or "--auth-token" is required');
|
20
|
-
}
|
21
|
-
};
|
22
|
-
|
23
6
|
program
|
24
7
|
.name('data-loader vendorcreds')
|
25
8
|
.description('Loads data into a db')
|
26
9
|
.usage('[options]')
|
27
10
|
.requiredOption(
|
28
11
|
'-c, --csv-filename <filename>',
|
29
|
-
'
|
12
|
+
'file name containing variables'
|
30
13
|
)
|
31
14
|
.requiredOption(
|
32
15
|
'-o, --offer-template-filename <filename>',
|
33
|
-
'
|
34
|
-
)
|
35
|
-
.requiredOption(
|
36
|
-
'-d, --did <did>',
|
37
|
-
'DID of the organization that should do the issuing'
|
16
|
+
'file name containing the credential template file'
|
38
17
|
)
|
18
|
+
.requiredOption('-d, --did <did>', "the issuer's DID")
|
39
19
|
.requiredOption(
|
40
20
|
'-p, --path <path>',
|
41
|
-
'
|
21
|
+
'the output directory to use where QR codes and output state files are stored'
|
42
22
|
)
|
43
23
|
.requiredOption(
|
44
24
|
'-t, --terms-url <termsUrl>',
|
45
|
-
'
|
25
|
+
'the url to the T&Cs that holder must consent to'
|
46
26
|
)
|
47
27
|
.option(
|
48
|
-
'--
|
49
|
-
|
28
|
+
'-m --identifier-match-column <identifierMatchColumn>',
|
29
|
+
`the column from the CSV for the user to be matched against the ID credential's "identifier" property
|
30
|
+
For example this should be the email column if matching against an Email credential type, or the phone number if
|
31
|
+
matching against a Phone credential type. Accepts header name or index. Default is 0.`,
|
32
|
+
parseColumn,
|
33
|
+
'0'
|
50
34
|
)
|
51
35
|
.option(
|
52
|
-
'-
|
53
|
-
|
36
|
+
'-u --vendor-userid-column <vendorUseridColumn>',
|
37
|
+
`the column from the CSV that is users id. Value is made available as "vendorUserId" in the offer template. Accepts
|
38
|
+
header name or index. Default is 0.`,
|
39
|
+
parseColumn,
|
40
|
+
'0'
|
54
41
|
)
|
55
42
|
.option(
|
56
|
-
'
|
57
|
-
'
|
43
|
+
'-e, --endpoint <url>',
|
44
|
+
'Credential Agent Endpoint to call to execute the issuing'
|
58
45
|
)
|
59
46
|
.option(
|
60
|
-
'--
|
61
|
-
'
|
47
|
+
'-a, --auth-token <url>',
|
48
|
+
'Bearer Auth Token to be used on the Agent API'
|
62
49
|
)
|
50
|
+
.option('-l, --label <label>', 'A label to attach to the documents inserted')
|
63
51
|
.option(
|
64
|
-
'--
|
65
|
-
'
|
52
|
+
'-v, --var <var...>',
|
53
|
+
'A variable that will be injected into the credential template renderer. use name=value'
|
66
54
|
)
|
67
55
|
.option(
|
68
|
-
'-
|
69
|
-
'
|
70
|
-
)
|
71
|
-
.option('-a, --auth-token <url>', 'Bearer Auth Token to use')
|
72
|
-
.option('-l, --label <label>', 'A label to attach to the documents inserted')
|
73
|
-
.option('-v, --var <var...>', 'A variable to add. use name=value')
|
74
|
-
.option(
|
75
|
-
'-y, --credential-type <credentialType>',
|
76
|
-
'The type of credentials. Default is EmailV1.0.',
|
56
|
+
'-y, --credential-type <idCredentialType>',
|
57
|
+
'the credential type used for identifying the user. Default is EmailV1.0.',
|
77
58
|
'EmailV1.0'
|
78
59
|
)
|
79
60
|
.option(
|
@@ -82,17 +63,32 @@ program
|
|
82
63
|
)
|
83
64
|
.option(
|
84
65
|
'--authTokenExpiresIn <authTokenExpiresIn>',
|
85
|
-
'The number of minutes that the offer will be available for after activation. Default is
|
86
|
-
'
|
66
|
+
'The number of minutes that the offer will be available for after activation. Default is 365 days.',
|
67
|
+
'525600'
|
87
68
|
)
|
88
69
|
.option('--new', 'Use a new disclosure for batch issuing')
|
89
70
|
.option(
|
90
71
|
'-i, --disclosure [disclosure]',
|
91
72
|
'An existing disclosure to use for the batch issuing'
|
92
73
|
)
|
74
|
+
.option(
|
75
|
+
'--legacy',
|
76
|
+
'the target credential agent is running in the "LEGACY" offer type mode. Default is false'
|
77
|
+
)
|
78
|
+
.option(
|
79
|
+
'-x --outputcsv',
|
80
|
+
"if passed an output csv is generated including the vendor's user id as the first column and the generated qrcode filename and deeplink"
|
81
|
+
)
|
82
|
+
.option(
|
83
|
+
'--x-name <outputCsvName>',
|
84
|
+
'The file name for the output CSV. Default is "output"'
|
85
|
+
)
|
86
|
+
.option(
|
87
|
+
'--dryrun',
|
88
|
+
'if passed in then a dry run executes showing how the data will be formatted'
|
89
|
+
)
|
93
90
|
.action(async () => {
|
94
91
|
const options = program.opts();
|
95
|
-
validateOptions(options);
|
96
92
|
// eslint-disable-next-line better-mutation/no-mutation
|
97
93
|
options.vars = parseVar(options.var);
|
98
94
|
printInfo(options);
|
@@ -113,3 +109,9 @@ program
|
|
113
109
|
}
|
114
110
|
})
|
115
111
|
.parseAsync(process.argv);
|
112
|
+
|
113
|
+
const parseVar = reduce((acc, pair) => {
|
114
|
+
const [key, value] = pair.split('=');
|
115
|
+
acc[key] = value;
|
116
|
+
return acc;
|
117
|
+
}, {});
|
@@ -1,93 +1,117 @@
|
|
1
|
-
const { omitBy, isNil, find, isString, isEmpty } = require('lodash/fp');
|
1
|
+
const { omitBy, isNil, find, isString, isEmpty, values } = require('lodash/fp');
|
2
2
|
const { validateDirectoryExists } = require('./validate-directory-exists');
|
3
3
|
const { initFetchers } = require('./fetchers');
|
4
|
-
const {
|
4
|
+
const {
|
5
|
+
prepareNewDisclosureRequest,
|
6
|
+
prepareExchangeOffers,
|
7
|
+
} = require('./prepare-data');
|
5
8
|
const { printInfo } = require('../helpers/common');
|
6
9
|
const {
|
7
10
|
writeQrCodeFile,
|
8
11
|
writeJsonFile,
|
9
12
|
writeOutputCsv,
|
10
13
|
} = require('./file-writers');
|
11
|
-
const { DisclosureType } = require('./constants');
|
14
|
+
const { CREDENTIAL_TYPES, DisclosureType } = require('./constants');
|
12
15
|
const {
|
13
16
|
askDisclosureType,
|
14
17
|
askDisclosureList,
|
15
18
|
askUseNewDisclosure,
|
16
19
|
} = require('./prompts');
|
20
|
+
const { loadCsv, getColName } = require('../helpers/load-csv');
|
17
21
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
return useNewDisclosure ? DisclosureType.NEW : null;
|
26
|
-
}
|
27
|
-
case isIntegratedMode && hasIntegratedDisclosures:
|
28
|
-
return askDisclosureType();
|
29
|
-
case Boolean(options.disclosure):
|
30
|
-
return DisclosureType.EXISTING;
|
31
|
-
default:
|
32
|
-
return DisclosureType.NEW;
|
33
|
-
}
|
22
|
+
const defaultOptions = {
|
23
|
+
vendorUseridColumn: 0,
|
24
|
+
identifierMatchColumn: 0,
|
25
|
+
authTokenExpiresIn: 525600,
|
26
|
+
legacy: false,
|
27
|
+
outputCsvName: 'output',
|
28
|
+
idCredentialType: 'EmailV1.0',
|
34
29
|
};
|
35
30
|
|
36
|
-
|
37
|
-
|
38
|
-
const
|
39
|
-
|
40
|
-
const disclosureType = await getDisclosureType(
|
41
|
-
!isEmpty(disclosures),
|
42
|
-
options
|
43
|
-
);
|
31
|
+
// eslint-disable-next-line consistent-return
|
32
|
+
const runBatchIssuing = async (opts) => {
|
33
|
+
const options = { ...defaultOptions, ...opts };
|
34
|
+
validateOptions(options);
|
44
35
|
|
45
|
-
|
46
|
-
return;
|
47
|
-
}
|
36
|
+
const context = { fetchers: initFetchers(options) };
|
48
37
|
|
49
|
-
const
|
50
|
-
|
38
|
+
const [csvHeaders, csvRows] = await loadCsv(options.csvFilename);
|
39
|
+
|
40
|
+
const disclosureRequest = await loadOrPrepareNewDisclosureRequest(
|
41
|
+
csvHeaders,
|
42
|
+
options,
|
43
|
+
context
|
44
|
+
);
|
45
|
+
|
46
|
+
const newExchangeOffers = await prepareExchangeOffers(
|
47
|
+
csvHeaders,
|
48
|
+
csvRows,
|
51
49
|
options
|
52
50
|
);
|
53
51
|
|
54
|
-
if (options.
|
52
|
+
if (options.dryrun) {
|
55
53
|
printInfo('Dry Run would create:');
|
56
54
|
printInfo(
|
57
55
|
JSON.stringify(
|
58
|
-
omitBy(isNil, {
|
56
|
+
omitBy(isNil, { disclosureRequest, newExchangeOffers }),
|
59
57
|
0,
|
60
58
|
2
|
61
59
|
)
|
62
60
|
);
|
63
|
-
|
61
|
+
|
62
|
+
return { disclosureRequest, newExchangeOffers };
|
64
63
|
}
|
65
64
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
newDisclosureRequest,
|
70
|
-
fetchers,
|
71
|
-
options,
|
72
|
-
});
|
65
|
+
if (disclosureRequest.id == null) {
|
66
|
+
await createDisclosureRequest(disclosureRequest, context);
|
67
|
+
}
|
73
68
|
|
74
|
-
|
69
|
+
await writeDisclosureToJson(disclosureRequest, options);
|
75
70
|
|
76
71
|
const outputs = options.legacy
|
77
72
|
? await runLegacyBatchIssuing(
|
78
73
|
disclosureRequest,
|
79
74
|
newExchangeOffers,
|
80
|
-
|
81
|
-
|
75
|
+
options,
|
76
|
+
context
|
82
77
|
)
|
83
78
|
: await runSingleQrCodeBatchIssuing(
|
84
79
|
disclosureRequest,
|
85
80
|
newExchangeOffers,
|
86
|
-
|
87
|
-
|
81
|
+
options,
|
82
|
+
context
|
88
83
|
);
|
89
84
|
|
90
|
-
writeOutput(outputs,
|
85
|
+
writeOutput(outputs, {
|
86
|
+
...options,
|
87
|
+
vendorUserIdColName: getColName(csvHeaders, options.vendorUseridColumn),
|
88
|
+
});
|
89
|
+
};
|
90
|
+
|
91
|
+
const loadExistingDisclosuresIfRequired = async (options, context) => {
|
92
|
+
if (options.new) {
|
93
|
+
return [];
|
94
|
+
}
|
95
|
+
|
96
|
+
const disclosures = await loadIntegratedIdentificationDisclosures(context);
|
97
|
+
if (options.disclosure) {
|
98
|
+
return disclosures;
|
99
|
+
}
|
100
|
+
|
101
|
+
// interactive mode is handled below
|
102
|
+
|
103
|
+
if (isEmpty(disclosures)) {
|
104
|
+
const useNewDisclosure = await askUseNewDisclosure();
|
105
|
+
if (!useNewDisclosure)
|
106
|
+
throw new Error(
|
107
|
+
'no existing disclosures on the target agent. Use a new disclosure'
|
108
|
+
);
|
109
|
+
|
110
|
+
return [];
|
111
|
+
}
|
112
|
+
|
113
|
+
const disclosureType = await askDisclosureType();
|
114
|
+
return disclosureType === DisclosureType.NEW ? [] : disclosures;
|
91
115
|
};
|
92
116
|
|
93
117
|
const writeOutput = (outputs, options) => {
|
@@ -99,19 +123,21 @@ const writeOutput = (outputs, options) => {
|
|
99
123
|
const runLegacyBatchIssuing = async (
|
100
124
|
disclosureRequest,
|
101
125
|
newExchangeOffers,
|
102
|
-
|
103
|
-
|
126
|
+
options,
|
127
|
+
context
|
104
128
|
) => {
|
105
129
|
const outputs = [];
|
106
130
|
for (const newExchangeOffer of newExchangeOffers) {
|
107
131
|
outputs.push(
|
108
132
|
// eslint-disable-next-line no-await-in-loop
|
109
|
-
await createOfferExchangeAndQrCode(
|
110
|
-
|
111
|
-
|
112
|
-
|
133
|
+
await createOfferExchangeAndQrCode(
|
134
|
+
{
|
135
|
+
...newExchangeOffer,
|
136
|
+
disclosureRequest,
|
137
|
+
},
|
113
138
|
options,
|
114
|
-
|
139
|
+
context
|
140
|
+
)
|
115
141
|
);
|
116
142
|
}
|
117
143
|
|
@@ -121,22 +147,24 @@ const runLegacyBatchIssuing = async (
|
|
121
147
|
const runSingleQrCodeBatchIssuing = async (
|
122
148
|
disclosureRequest,
|
123
149
|
newExchangeOffers,
|
124
|
-
|
125
|
-
|
150
|
+
options,
|
151
|
+
context
|
126
152
|
) => {
|
127
153
|
const outputs = [];
|
128
154
|
for (const newExchangeOffer of newExchangeOffers) {
|
129
155
|
outputs.push(
|
130
156
|
// eslint-disable-next-line no-await-in-loop
|
131
|
-
await createOfferExchange(
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
157
|
+
await createOfferExchange(
|
158
|
+
{
|
159
|
+
...newExchangeOffer,
|
160
|
+
disclosureRequest,
|
161
|
+
},
|
162
|
+
context
|
163
|
+
)
|
137
164
|
);
|
138
165
|
}
|
139
166
|
|
167
|
+
const { fetchers } = context;
|
140
168
|
printInfo('Generating qrcode & deep link');
|
141
169
|
const deeplink = await fetchers.loadDisclosureDeeplink(disclosureRequest);
|
142
170
|
printInfo(`Deep link: ${deeplink}`);
|
@@ -147,21 +175,32 @@ const runSingleQrCodeBatchIssuing = async (
|
|
147
175
|
return outputs;
|
148
176
|
};
|
149
177
|
|
150
|
-
const
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
178
|
+
const loadOrPrepareNewDisclosureRequest = async (
|
179
|
+
csvHeaders,
|
180
|
+
options,
|
181
|
+
context
|
182
|
+
) => {
|
183
|
+
const disclosures = await loadExistingDisclosuresIfRequired(options, context);
|
155
184
|
|
156
|
-
|
157
|
-
|
185
|
+
if (isEmpty(disclosures)) {
|
186
|
+
return prepareNewDisclosureRequest(csvHeaders, options);
|
187
|
+
}
|
158
188
|
|
159
|
-
|
160
|
-
|
189
|
+
const disclosureId = isString(options.disclosure)
|
190
|
+
? options.disclosure
|
191
|
+
: await askDisclosureList(disclosures);
|
192
|
+
const disclosure = find({ id: disclosureId }, disclosures);
|
193
|
+
if (disclosure == null) {
|
194
|
+
throw new Error('existing disclosure not found');
|
161
195
|
}
|
196
|
+
return disclosure;
|
197
|
+
};
|
162
198
|
|
163
|
-
|
164
|
-
|
199
|
+
const loadIntegratedIdentificationDisclosures = async ({ fetchers }) =>
|
200
|
+
fetchers.getDisclosureList(['integrated-issuing-identification']);
|
201
|
+
|
202
|
+
const createDisclosureRequest = async (newDisclosureRequest, { fetchers }) => {
|
203
|
+
return fetchers.createDisclosure(newDisclosureRequest);
|
165
204
|
};
|
166
205
|
|
167
206
|
const writeDisclosureToJson = async (disclosureRequest, options) => {
|
@@ -183,16 +222,13 @@ const writeDisclosureToJson = async (disclosureRequest, options) => {
|
|
183
222
|
'lastrun',
|
184
223
|
options
|
185
224
|
);
|
186
|
-
return disclosureRequest;
|
187
225
|
};
|
188
226
|
|
189
|
-
const createOfferExchangeAndQrCode = async (
|
190
|
-
newExchange,
|
191
|
-
newOffer,
|
192
|
-
disclosureRequest,
|
227
|
+
const createOfferExchangeAndQrCode = async (
|
228
|
+
{ newExchange, newOffer, disclosureRequest },
|
193
229
|
options,
|
194
|
-
fetchers
|
195
|
-
|
230
|
+
{ fetchers }
|
231
|
+
) => {
|
196
232
|
const { exchange, offer, vendorUserId } = await createOfferExchange({
|
197
233
|
newExchange,
|
198
234
|
newOffer,
|
@@ -220,12 +256,10 @@ const createOfferExchangeAndQrCode = async ({
|
|
220
256
|
};
|
221
257
|
};
|
222
258
|
|
223
|
-
const createOfferExchange = async (
|
224
|
-
newExchange,
|
225
|
-
|
226
|
-
|
227
|
-
fetchers,
|
228
|
-
}) => {
|
259
|
+
const createOfferExchange = async (
|
260
|
+
{ newExchange, newOffer, disclosureRequest },
|
261
|
+
{ fetchers }
|
262
|
+
) => {
|
229
263
|
const { vendorUserId } = newOffer.credentialSubject;
|
230
264
|
printInfo(`Setting up vendorUserId:${vendorUserId}`);
|
231
265
|
const exchange = await fetchers.createOfferExchange({
|
@@ -241,18 +275,31 @@ const createOfferExchange = async ({
|
|
241
275
|
};
|
242
276
|
};
|
243
277
|
|
244
|
-
const
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
278
|
+
const validateOptions = (options) => {
|
279
|
+
if (options.dryrun == null && options.endpoint == null) {
|
280
|
+
throw new Error(
|
281
|
+
'"-e" or "--endpoint" is required unless executing a "dryrun"'
|
282
|
+
);
|
283
|
+
}
|
284
|
+
if (options.endpoint != null && options.authToken == null) {
|
285
|
+
throw new Error('"-a" or "--auth-token" is required');
|
286
|
+
}
|
287
|
+
|
288
|
+
validateDirectoryExists(options);
|
289
|
+
|
290
|
+
validateCredentialType(options.idCredentialType);
|
291
|
+
};
|
292
|
+
|
293
|
+
const validateCredentialType = (idCredentialType) => {
|
294
|
+
const allowedIdCredentialTypes = values(CREDENTIAL_TYPES);
|
295
|
+
if (
|
296
|
+
!idCredentialType ||
|
297
|
+
!allowedIdCredentialTypes.includes(idCredentialType)
|
298
|
+
) {
|
299
|
+
throw new Error(
|
300
|
+
`${idCredentialType} doesn't exist. Please use one of ${allowedIdCredentialTypes}`
|
301
|
+
);
|
302
|
+
}
|
256
303
|
};
|
257
304
|
|
258
305
|
module.exports = { runBatchIssuing };
|