@slothmoney/agent-cli 0.2.0 → 0.3.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/CHANGELOG.md +22 -0
- package/README.md +159 -41
- package/dist/args.js +302 -2
- package/dist/cli.js +607 -5
- package/dist/contracts.js +96 -2
- package/package.json +1 -1
package/dist/contracts.js
CHANGED
|
@@ -38,12 +38,18 @@ function validateAssignment(value, index) {
|
|
|
38
38
|
const assignment = requireObject(value, label);
|
|
39
39
|
rejectUnknownFields(assignment, new Set([
|
|
40
40
|
'transactionRef',
|
|
41
|
+
'assignmentScope',
|
|
41
42
|
'categoryId',
|
|
42
43
|
'lineItemId',
|
|
43
44
|
'categorySplits',
|
|
44
45
|
'incomeSubtype',
|
|
45
46
|
]), label);
|
|
46
47
|
requireString(assignment.transactionRef, `${label}.transactionRef`);
|
|
48
|
+
if (assignment.assignmentScope !== undefined
|
|
49
|
+
&& assignment.assignmentScope !== 'personal'
|
|
50
|
+
&& assignment.assignmentScope !== 'joint') {
|
|
51
|
+
throw new UsageError(`${label}.assignmentScope must be personal or joint`);
|
|
52
|
+
}
|
|
47
53
|
if (assignment.categoryId !== undefined && assignment.categoryId !== null) {
|
|
48
54
|
requireString(assignment.categoryId, `${label}.categoryId`);
|
|
49
55
|
}
|
|
@@ -74,6 +80,9 @@ function validateAssignment(value, index) {
|
|
|
74
80
|
}
|
|
75
81
|
return {
|
|
76
82
|
transactionRef: assignment.transactionRef,
|
|
83
|
+
...(assignment.assignmentScope !== undefined
|
|
84
|
+
? { assignmentScope: assignment.assignmentScope }
|
|
85
|
+
: {}),
|
|
77
86
|
...(assignment.categoryId !== undefined ? { categoryId: assignment.categoryId } : {}),
|
|
78
87
|
...(assignment.lineItemId !== undefined ? { lineItemId: assignment.lineItemId } : {}),
|
|
79
88
|
...(categorySplits !== undefined ? { categorySplits } : {}),
|
|
@@ -130,6 +139,20 @@ function isTransaction(value) {
|
|
|
130
139
|
&& (value.categoryId === null || typeof value.categoryId === 'string')
|
|
131
140
|
&& (value.lineItemId === null || typeof value.lineItemId === 'string')
|
|
132
141
|
&& Array.isArray(value.categorySplits)
|
|
142
|
+
&& (value.jointBudgetContribution === null
|
|
143
|
+
|| (isObject(value.jointBudgetContribution)
|
|
144
|
+
&& typeof value.jointBudgetContribution.eligible === 'boolean'
|
|
145
|
+
&& typeof value.jointBudgetContribution.included === 'boolean'
|
|
146
|
+
&& Number.isInteger(value.jointBudgetContribution.amountPence)
|
|
147
|
+
&& Number(value.jointBudgetContribution.amountPence) > 0
|
|
148
|
+
&& (value.jointBudgetContribution.categoryId === null
|
|
149
|
+
|| typeof value.jointBudgetContribution.categoryId === 'string')
|
|
150
|
+
&& (value.jointBudgetContribution.lineItemId === null
|
|
151
|
+
|| typeof value.jointBudgetContribution.lineItemId === 'string')
|
|
152
|
+
&& Array.isArray(value.jointBudgetContribution.categorySplits)
|
|
153
|
+
&& (value.jointBudgetContribution.incomeSubtype === null
|
|
154
|
+
|| value.jointBudgetContribution.incomeSubtype === 'pay'
|
|
155
|
+
|| value.jointBudgetContribution.incomeSubtype === 'interest')))
|
|
133
156
|
&& (value.incomeSubtype === null
|
|
134
157
|
|| value.incomeSubtype === 'pay'
|
|
135
158
|
|| value.incomeSubtype === 'interest'));
|
|
@@ -143,12 +166,28 @@ function isTransactionsResponse(value) {
|
|
|
143
166
|
function isAssignmentResponse(value) {
|
|
144
167
|
return (isObject(value)
|
|
145
168
|
&& Array.isArray(value.succeeded)
|
|
146
|
-
&& value.succeeded.every((item) => isObject(item)
|
|
169
|
+
&& value.succeeded.every((item) => (isObject(item)
|
|
170
|
+
&& typeof item.transactionRef === 'string'
|
|
171
|
+
&& (item.assignmentScope === 'personal' || item.assignmentScope === 'joint')))
|
|
147
172
|
&& Array.isArray(value.failed)
|
|
148
173
|
&& value.failed.every((item) => (isObject(item)
|
|
149
174
|
&& typeof item.error === 'string'
|
|
150
175
|
&& (item.transactionRef === undefined || typeof item.transactionRef === 'string'))));
|
|
151
176
|
}
|
|
177
|
+
export function validateJointBudgetSettingsResponse(value) {
|
|
178
|
+
if (!isObject(value)
|
|
179
|
+
|| Object.keys(value).some((key) => !new Set([
|
|
180
|
+
'includeSharedPersonalTransactions',
|
|
181
|
+
'updatedAt',
|
|
182
|
+
'updatedBy',
|
|
183
|
+
]).has(key))
|
|
184
|
+
|| typeof value.includeSharedPersonalTransactions !== 'boolean'
|
|
185
|
+
|| (value.updatedAt !== null && !isIsoDateTime(value.updatedAt))
|
|
186
|
+
|| (value.updatedBy !== null && typeof value.updatedBy !== 'string')) {
|
|
187
|
+
throw new ApiError('Invalid joint budget settings response from the Agent API');
|
|
188
|
+
}
|
|
189
|
+
return value;
|
|
190
|
+
}
|
|
152
191
|
function isHttpUrl(value) {
|
|
153
192
|
if (typeof value !== 'string')
|
|
154
193
|
return false;
|
|
@@ -175,6 +214,55 @@ function isPartnerResponse(value) {
|
|
|
175
214
|
&& isIsoDateTime(value.expiresAt)
|
|
176
215
|
&& value.status === 'open');
|
|
177
216
|
}
|
|
217
|
+
function hasOnlyFields(value, fields) {
|
|
218
|
+
const allowed = new Set(fields);
|
|
219
|
+
return Object.keys(value).every((key) => allowed.has(key));
|
|
220
|
+
}
|
|
221
|
+
function isGoal(value) {
|
|
222
|
+
return (isObject(value)
|
|
223
|
+
&& hasOnlyFields(value, [
|
|
224
|
+
'id',
|
|
225
|
+
'name',
|
|
226
|
+
'targetAmount',
|
|
227
|
+
'targetMonthKey',
|
|
228
|
+
'isAchieved',
|
|
229
|
+
'sharedWithPartner',
|
|
230
|
+
])
|
|
231
|
+
&& typeof value.id === 'string'
|
|
232
|
+
&& value.id.trim().length > 0
|
|
233
|
+
&& typeof value.name === 'string'
|
|
234
|
+
&& value.name.trim().length > 0
|
|
235
|
+
&& (value.targetAmount === null
|
|
236
|
+
|| (typeof value.targetAmount === 'number' && Number.isFinite(value.targetAmount)))
|
|
237
|
+
&& (value.targetMonthKey === null
|
|
238
|
+
|| (typeof value.targetMonthKey === 'string'
|
|
239
|
+
&& /^\d{4}-(0[1-9]|1[0-2])$/.test(value.targetMonthKey)))
|
|
240
|
+
&& typeof value.isAchieved === 'boolean'
|
|
241
|
+
&& typeof value.sharedWithPartner === 'boolean');
|
|
242
|
+
}
|
|
243
|
+
function isCurrency(value) {
|
|
244
|
+
return typeof value === 'string' && /^[A-Z]{3}$/.test(value);
|
|
245
|
+
}
|
|
246
|
+
function isGoalsResponse(value) {
|
|
247
|
+
return (isObject(value)
|
|
248
|
+
&& hasOnlyFields(value, ['currency', 'goals'])
|
|
249
|
+
&& isCurrency(value.currency)
|
|
250
|
+
&& Array.isArray(value.goals)
|
|
251
|
+
&& value.goals.every(isGoal));
|
|
252
|
+
}
|
|
253
|
+
function isGoalMutationResponse(value) {
|
|
254
|
+
return (isObject(value)
|
|
255
|
+
&& hasOnlyFields(value, ['currency', 'goal'])
|
|
256
|
+
&& isCurrency(value.currency)
|
|
257
|
+
&& isGoal(value.goal));
|
|
258
|
+
}
|
|
259
|
+
function isGoalDeleteResponse(value) {
|
|
260
|
+
return (isObject(value)
|
|
261
|
+
&& hasOnlyFields(value, ['deleted', 'deletedGoalId'])
|
|
262
|
+
&& value.deleted === true
|
|
263
|
+
&& typeof value.deletedGoalId === 'string'
|
|
264
|
+
&& value.deletedGoalId.trim().length > 0);
|
|
265
|
+
}
|
|
178
266
|
export function parseApiResponse(command, value) {
|
|
179
267
|
const valid = command === 'categories'
|
|
180
268
|
? isCategoryResponse(value)
|
|
@@ -182,7 +270,13 @@ export function parseApiResponse(command, value) {
|
|
|
182
270
|
? isTransactionsResponse(value)
|
|
183
271
|
: command === 'assign'
|
|
184
272
|
? isAssignmentResponse(value)
|
|
185
|
-
:
|
|
273
|
+
: command === 'ask-partner'
|
|
274
|
+
? isPartnerResponse(value)
|
|
275
|
+
: command === 'goals-list'
|
|
276
|
+
? isGoalsResponse(value)
|
|
277
|
+
: command === 'goals-delete'
|
|
278
|
+
? isGoalDeleteResponse(value)
|
|
279
|
+
: isGoalMutationResponse(value);
|
|
186
280
|
if (!valid) {
|
|
187
281
|
const label = command === 'assign' ? 'assignment' : command;
|
|
188
282
|
throw new ApiError(`Invalid ${label} response from the Agent API`);
|