allsquare 0.1.1
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 +16 -0
- package/LICENSE +21 -0
- package/README.md +234 -0
- package/dist/api/client.d.ts +46 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +162 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/contract.d.ts +549 -0
- package/dist/api/contract.d.ts.map +1 -0
- package/dist/api/contract.js +49 -0
- package/dist/api/contract.js.map +1 -0
- package/dist/api/model.d.ts +627 -0
- package/dist/api/model.d.ts.map +1 -0
- package/dist/api/model.js +378 -0
- package/dist/api/model.js.map +1 -0
- package/dist/auth/auth-service.d.ts +34 -0
- package/dist/auth/auth-service.d.ts.map +1 -0
- package/dist/auth/auth-service.js +221 -0
- package/dist/auth/auth-service.js.map +1 -0
- package/dist/auth/browser.d.ts +12 -0
- package/dist/auth/browser.d.ts.map +1 -0
- package/dist/auth/browser.js +50 -0
- package/dist/auth/browser.js.map +1 -0
- package/dist/auth/credential-store.d.ts +28 -0
- package/dist/auth/credential-store.d.ts.map +1 -0
- package/dist/auth/credential-store.js +75 -0
- package/dist/auth/credential-store.js.map +1 -0
- package/dist/auth/installation-store.d.ts +14 -0
- package/dist/auth/installation-store.d.ts.map +1 -0
- package/dist/auth/installation-store.js +122 -0
- package/dist/auth/installation-store.js.map +1 -0
- package/dist/auth/model.d.ts +54 -0
- package/dist/auth/model.d.ts.map +1 -0
- package/dist/auth/model.js +24 -0
- package/dist/auth/model.js.map +1 -0
- package/dist/auth/oauth-callback.d.ts +17 -0
- package/dist/auth/oauth-callback.d.ts.map +1 -0
- package/dist/auth/oauth-callback.js +94 -0
- package/dist/auth/oauth-callback.js.map +1 -0
- package/dist/auth/oauth-client.d.ts +43 -0
- package/dist/auth/oauth-client.d.ts.map +1 -0
- package/dist/auth/oauth-client.js +191 -0
- package/dist/auth/oauth-client.js.map +1 -0
- package/dist/auth/pkce.d.ts +9 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +12 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/command.d.ts +3 -0
- package/dist/command.d.ts.map +1 -0
- package/dist/command.js +24 -0
- package/dist/command.js.map +1 -0
- package/dist/commands/agent-guide.d.ts +5 -0
- package/dist/commands/agent-guide.d.ts.map +1 -0
- package/dist/commands/agent-guide.js +226 -0
- package/dist/commands/agent-guide.js.map +1 -0
- package/dist/commands/auth.d.ts +5 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +68 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/balances.d.ts +5 -0
- package/dist/commands/balances.d.ts.map +1 -0
- package/dist/commands/balances.js +106 -0
- package/dist/commands/balances.js.map +1 -0
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +16 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/expense-input.d.ts +17 -0
- package/dist/commands/expense-input.d.ts.map +1 -0
- package/dist/commands/expense-input.js +78 -0
- package/dist/commands/expense-input.js.map +1 -0
- package/dist/commands/expenses.d.ts +5 -0
- package/dist/commands/expenses.d.ts.map +1 -0
- package/dist/commands/expenses.js +419 -0
- package/dist/commands/expenses.js.map +1 -0
- package/dist/commands/groups.d.ts +5 -0
- package/dist/commands/groups.d.ts.map +1 -0
- package/dist/commands/groups.js +149 -0
- package/dist/commands/groups.js.map +1 -0
- package/dist/commands/recurring-expenses.d.ts +5 -0
- package/dist/commands/recurring-expenses.d.ts.map +1 -0
- package/dist/commands/recurring-expenses.js +416 -0
- package/dist/commands/recurring-expenses.js.map +1 -0
- package/dist/commands/settlements.d.ts +5 -0
- package/dist/commands/settlements.d.ts.map +1 -0
- package/dist/commands/settlements.js +225 -0
- package/dist/commands/settlements.js.map +1 -0
- package/dist/commands/shared.d.ts +6 -0
- package/dist/commands/shared.d.ts.map +1 -0
- package/dist/commands/shared.js +35 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/commands/spend-summary.d.ts +5 -0
- package/dist/commands/spend-summary.d.ts.map +1 -0
- package/dist/commands/spend-summary.js +107 -0
- package/dist/commands/spend-summary.js.map +1 -0
- package/dist/commands/update.d.ts +9 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +78 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +52 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +87 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +183 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/interaction.d.ts +16 -0
- package/dist/interaction.d.ts.map +1 -0
- package/dist/interaction.js +14 -0
- package/dist/interaction.js.map +1 -0
- package/dist/layers.d.ts +13 -0
- package/dist/layers.d.ts.map +1 -0
- package/dist/layers.js +17 -0
- package/dist/layers.js.map +1 -0
- package/dist/output.d.ts +31 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +26 -0
- package/dist/output.js.map +1 -0
- package/dist/update/update-service.d.ts +41 -0
- package/dist/update/update-service.d.ts.map +1 -0
- package/dist/update/update-service.js +231 -0
- package/dist/update/update-service.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
const Id = Schema.String;
|
|
3
|
+
const NullableString = Schema.NullOr(Schema.String);
|
|
4
|
+
// Currencies the API accepts on writes. Responses keep plain strings because
|
|
5
|
+
// older records may hold other codes. The repository contract test keeps this
|
|
6
|
+
// list in step with the server.
|
|
7
|
+
export const SUPPORTED_CURRENCIES = ["USD", "CAD", "EUR", "GBP"];
|
|
8
|
+
export const Currency = Schema.Literals(SUPPORTED_CURRENCIES);
|
|
9
|
+
export const Group = Schema.Struct({
|
|
10
|
+
id: Id,
|
|
11
|
+
name: Schema.String,
|
|
12
|
+
defaultCurrency: Schema.String
|
|
13
|
+
});
|
|
14
|
+
export const ListGroupsResponse = Schema.Struct({
|
|
15
|
+
groups: Schema.Array(Group)
|
|
16
|
+
});
|
|
17
|
+
export const GroupMember = Schema.Struct({
|
|
18
|
+
id: Id,
|
|
19
|
+
name: Schema.String,
|
|
20
|
+
email: NullableString,
|
|
21
|
+
isCurrentUser: Schema.Boolean,
|
|
22
|
+
venmoUsername: NullableString
|
|
23
|
+
});
|
|
24
|
+
export const ListGroupMembersResponse = Schema.Struct({
|
|
25
|
+
groupId: Id,
|
|
26
|
+
currentUserId: Id,
|
|
27
|
+
members: Schema.Array(GroupMember)
|
|
28
|
+
});
|
|
29
|
+
export const CreateGroupRequest = Schema.Struct({
|
|
30
|
+
name: Schema.String.check(Schema.isLengthBetween(1, 100)),
|
|
31
|
+
currency: Currency,
|
|
32
|
+
memberEmails: Schema.optionalKey(Schema.Array(Schema.String).check(Schema.isLengthBetween(0, 20)))
|
|
33
|
+
});
|
|
34
|
+
export const CreateGroupResponse = Schema.Struct({
|
|
35
|
+
group: Group,
|
|
36
|
+
membersAdded: Schema.Number,
|
|
37
|
+
membersNotified: Schema.Number,
|
|
38
|
+
invitationsCreated: Schema.Number,
|
|
39
|
+
invitationEmailsSent: Schema.Number
|
|
40
|
+
});
|
|
41
|
+
export const AddGroupMemberRequest = Schema.Struct({
|
|
42
|
+
email: Schema.String
|
|
43
|
+
});
|
|
44
|
+
export const AddGroupMemberResponse = Schema.Union([
|
|
45
|
+
Schema.Struct({
|
|
46
|
+
status: Schema.Literals(["added", "rejoined"]),
|
|
47
|
+
groupId: Id,
|
|
48
|
+
email: Schema.String,
|
|
49
|
+
userId: Id,
|
|
50
|
+
emailSent: Schema.Boolean
|
|
51
|
+
}),
|
|
52
|
+
Schema.Struct({
|
|
53
|
+
status: Schema.Literal("invited"),
|
|
54
|
+
groupId: Id,
|
|
55
|
+
email: Schema.String,
|
|
56
|
+
expiresAt: Schema.String,
|
|
57
|
+
emailSent: Schema.Boolean
|
|
58
|
+
})
|
|
59
|
+
]);
|
|
60
|
+
export const BalanceEntry = Schema.Struct({
|
|
61
|
+
userId: Id,
|
|
62
|
+
name: Schema.String,
|
|
63
|
+
amount: Schema.Number
|
|
64
|
+
});
|
|
65
|
+
export const CurrencyTotals = Schema.Struct({
|
|
66
|
+
youOwe: Schema.Number,
|
|
67
|
+
youAreOwed: Schema.Number,
|
|
68
|
+
net: Schema.Number
|
|
69
|
+
});
|
|
70
|
+
export const GetAllBalancesResponse = Schema.Struct({
|
|
71
|
+
currentUserId: Id,
|
|
72
|
+
groups: Schema.Array(Schema.Struct({
|
|
73
|
+
groupId: Id,
|
|
74
|
+
groupName: NullableString,
|
|
75
|
+
currency: Schema.String,
|
|
76
|
+
youOwe: Schema.Array(BalanceEntry),
|
|
77
|
+
youAreOwed: Schema.Array(BalanceEntry),
|
|
78
|
+
net: Schema.Number
|
|
79
|
+
})),
|
|
80
|
+
totalsByCurrency: Schema.Record(Schema.String, CurrencyTotals),
|
|
81
|
+
byPerson: Schema.Array(Schema.Struct({
|
|
82
|
+
userId: Id,
|
|
83
|
+
name: Schema.String,
|
|
84
|
+
amount: Schema.Number,
|
|
85
|
+
currency: Schema.String,
|
|
86
|
+
direction: Schema.Literals(["you_owe", "owes_you"])
|
|
87
|
+
}))
|
|
88
|
+
});
|
|
89
|
+
export const FormattedBalanceEntry = Schema.Struct({
|
|
90
|
+
userId: Id,
|
|
91
|
+
name: Schema.String,
|
|
92
|
+
amount: Schema.String,
|
|
93
|
+
currency: Schema.String
|
|
94
|
+
});
|
|
95
|
+
export const GetGroupBalancesResponse = Schema.Struct({
|
|
96
|
+
groupId: Id,
|
|
97
|
+
currency: Schema.String,
|
|
98
|
+
totalSpent: Schema.String,
|
|
99
|
+
youOwe: Schema.Array(FormattedBalanceEntry),
|
|
100
|
+
youAreOwed: Schema.Array(FormattedBalanceEntry)
|
|
101
|
+
});
|
|
102
|
+
export const ExpenseSplit = Schema.Struct({
|
|
103
|
+
userId: Id,
|
|
104
|
+
name: Schema.String,
|
|
105
|
+
amount: Schema.NullOr(Schema.Number),
|
|
106
|
+
percentage: Schema.NullOr(Schema.Number),
|
|
107
|
+
splitType: Schema.String
|
|
108
|
+
});
|
|
109
|
+
export const Expense = Schema.Struct({
|
|
110
|
+
id: Id,
|
|
111
|
+
description: Schema.String,
|
|
112
|
+
amount: Schema.Number,
|
|
113
|
+
currency: Schema.String,
|
|
114
|
+
date: NullableString,
|
|
115
|
+
payer: Schema.Struct({
|
|
116
|
+
id: NullableString,
|
|
117
|
+
name: Schema.String
|
|
118
|
+
}),
|
|
119
|
+
splits: Schema.Array(ExpenseSplit),
|
|
120
|
+
isSettled: Schema.Boolean,
|
|
121
|
+
isRecurring: Schema.Boolean,
|
|
122
|
+
groupId: Id,
|
|
123
|
+
groupName: NullableString
|
|
124
|
+
});
|
|
125
|
+
export const ListExpensesResponse = Schema.Struct({
|
|
126
|
+
currentUserId: Id,
|
|
127
|
+
expenses: Schema.Array(Expense),
|
|
128
|
+
nextCursor: NullableString
|
|
129
|
+
});
|
|
130
|
+
export const GetExpenseResponse = Schema.Struct({
|
|
131
|
+
currentUserId: Id,
|
|
132
|
+
expense: Expense
|
|
133
|
+
});
|
|
134
|
+
export const CreateExpenseRequest = Schema.Struct({
|
|
135
|
+
description: Schema.String.check(Schema.isLengthBetween(1, 200)),
|
|
136
|
+
amount: Schema.Number.check(Schema.isGreaterThan(0)),
|
|
137
|
+
currency: Currency,
|
|
138
|
+
paidById: Schema.optionalKey(Id),
|
|
139
|
+
splitWith: Schema.Array(Id),
|
|
140
|
+
splitType: Schema.Literals(["amount", "percentage", "exact"]),
|
|
141
|
+
date: Schema.optionalKey(Schema.String),
|
|
142
|
+
percentageSplits: Schema.optionalKey(Schema.Record(Schema.String, Schema.Number)),
|
|
143
|
+
exactSplits: Schema.optionalKey(Schema.Record(Schema.String, Schema.Number))
|
|
144
|
+
});
|
|
145
|
+
export const CreateExpenseResponse = Schema.Struct({
|
|
146
|
+
expense: Schema.Struct({
|
|
147
|
+
id: Id,
|
|
148
|
+
description: Schema.String,
|
|
149
|
+
amount: Schema.Number,
|
|
150
|
+
currency: Schema.String,
|
|
151
|
+
date: Schema.String,
|
|
152
|
+
groupId: Id
|
|
153
|
+
})
|
|
154
|
+
});
|
|
155
|
+
export const UpdateExpenseRequest = Schema.Struct({
|
|
156
|
+
description: Schema.optionalKey(Schema.String.check(Schema.isLengthBetween(1, 200))),
|
|
157
|
+
amount: Schema.optionalKey(Schema.Number.check(Schema.isGreaterThan(0))),
|
|
158
|
+
currency: Schema.optionalKey(Currency),
|
|
159
|
+
paidById: Schema.optionalKey(Id),
|
|
160
|
+
splitWith: Schema.optionalKey(Schema.Array(Id)),
|
|
161
|
+
splitType: Schema.optionalKey(Schema.Literals(["amount", "percentage", "exact"])),
|
|
162
|
+
date: Schema.optionalKey(Schema.String),
|
|
163
|
+
percentageSplits: Schema.optionalKey(Schema.Record(Schema.String, Schema.Number)),
|
|
164
|
+
exactSplits: Schema.optionalKey(Schema.Record(Schema.String, Schema.Number))
|
|
165
|
+
});
|
|
166
|
+
export const UpdateExpenseResponse = Schema.Struct({ expense: Expense });
|
|
167
|
+
export const DeleteExpenseRequest = Schema.Struct({
|
|
168
|
+
confirmed: Schema.Literal(true),
|
|
169
|
+
userIntent: Schema.String.check(Schema.isLengthBetween(1, 500))
|
|
170
|
+
});
|
|
171
|
+
export const DeleteExpenseResponse = Schema.Struct({
|
|
172
|
+
deleted: Schema.Literal(true),
|
|
173
|
+
expense: Schema.Struct({
|
|
174
|
+
id: Id,
|
|
175
|
+
description: Schema.String,
|
|
176
|
+
amount: Schema.Number,
|
|
177
|
+
currency: Schema.String,
|
|
178
|
+
groupId: Id
|
|
179
|
+
})
|
|
180
|
+
});
|
|
181
|
+
export const RecurringExpense = Schema.Struct({
|
|
182
|
+
id: Id,
|
|
183
|
+
groupId: Id,
|
|
184
|
+
groupName: NullableString,
|
|
185
|
+
description: Schema.String,
|
|
186
|
+
amount: Schema.Number,
|
|
187
|
+
currency: Schema.String,
|
|
188
|
+
frequency: Schema.String,
|
|
189
|
+
schedule: Schema.String,
|
|
190
|
+
nextOccurrence: Schema.String,
|
|
191
|
+
lastGeneratedAt: NullableString,
|
|
192
|
+
isPaused: Schema.Boolean,
|
|
193
|
+
pausedAt: NullableString,
|
|
194
|
+
payer: Schema.Struct({
|
|
195
|
+
id: Id,
|
|
196
|
+
name: Schema.String
|
|
197
|
+
}),
|
|
198
|
+
splitType: Schema.String,
|
|
199
|
+
splits: Schema.Array(Schema.Struct({
|
|
200
|
+
userId: Id,
|
|
201
|
+
name: Schema.String,
|
|
202
|
+
amount: Schema.NullOr(Schema.Number),
|
|
203
|
+
percentage: Schema.NullOr(Schema.Number)
|
|
204
|
+
})),
|
|
205
|
+
createdById: Id,
|
|
206
|
+
canEdit: Schema.Boolean
|
|
207
|
+
});
|
|
208
|
+
export const ListRecurringExpensesResponse = Schema.Struct({
|
|
209
|
+
currentUserId: Id,
|
|
210
|
+
recurringExpenses: Schema.Array(RecurringExpense)
|
|
211
|
+
});
|
|
212
|
+
export const GetRecurringExpenseResponse = Schema.Struct({
|
|
213
|
+
currentUserId: Id,
|
|
214
|
+
recurringExpense: RecurringExpense
|
|
215
|
+
});
|
|
216
|
+
const SplitType = Schema.Literals(["amount", "percentage", "exact"]);
|
|
217
|
+
const RecurrenceFrequency = Schema.Literals([
|
|
218
|
+
"weekly",
|
|
219
|
+
"biweekly",
|
|
220
|
+
"monthly",
|
|
221
|
+
"yearly"
|
|
222
|
+
]);
|
|
223
|
+
const SplitAllocations = Schema.Record(Schema.String, Schema.Number);
|
|
224
|
+
export const CreateRecurringExpenseRequest = Schema.Struct({
|
|
225
|
+
description: Schema.String.check(Schema.isLengthBetween(1, 200)),
|
|
226
|
+
amount: Schema.Number.check(Schema.isGreaterThan(0)),
|
|
227
|
+
currency: Currency,
|
|
228
|
+
paidById: Schema.optionalKey(Id),
|
|
229
|
+
splitWith: Schema.Array(Id),
|
|
230
|
+
splitType: SplitType,
|
|
231
|
+
frequency: RecurrenceFrequency,
|
|
232
|
+
startDate: Schema.optionalKey(Schema.String),
|
|
233
|
+
percentageSplits: Schema.optionalKey(SplitAllocations),
|
|
234
|
+
exactSplits: Schema.optionalKey(SplitAllocations)
|
|
235
|
+
});
|
|
236
|
+
export const CreateRecurringExpenseResponse = Schema.Struct({
|
|
237
|
+
recurringExpense: Schema.Struct({
|
|
238
|
+
id: Id,
|
|
239
|
+
description: Schema.String,
|
|
240
|
+
amount: Schema.Number,
|
|
241
|
+
currency: Schema.String,
|
|
242
|
+
frequency: Schema.String,
|
|
243
|
+
nextOccurrence: Schema.String,
|
|
244
|
+
groupId: Id,
|
|
245
|
+
immediateExpenseCreated: Schema.Boolean,
|
|
246
|
+
// Absent in replays of creates stored before the server added it.
|
|
247
|
+
immediateExpenseId: Schema.optionalKey(Schema.NullOr(Id))
|
|
248
|
+
})
|
|
249
|
+
});
|
|
250
|
+
export const UpdateRecurringExpenseRequest = Schema.Struct({
|
|
251
|
+
description: Schema.optionalKey(Schema.String.check(Schema.isLengthBetween(1, 200))),
|
|
252
|
+
amount: Schema.optionalKey(Schema.Number.check(Schema.isGreaterThan(0))),
|
|
253
|
+
paidById: Schema.optionalKey(Id),
|
|
254
|
+
splitWith: Schema.optionalKey(Schema.Array(Id)),
|
|
255
|
+
splitType: Schema.optionalKey(SplitType),
|
|
256
|
+
frequency: Schema.optionalKey(RecurrenceFrequency),
|
|
257
|
+
percentageSplits: Schema.optionalKey(SplitAllocations),
|
|
258
|
+
exactSplits: Schema.optionalKey(SplitAllocations)
|
|
259
|
+
});
|
|
260
|
+
export const RecurringExpenseMutationResponse = Schema.Struct({
|
|
261
|
+
recurringExpense: RecurringExpense
|
|
262
|
+
});
|
|
263
|
+
export const SetRecurringExpensePausedRequest = Schema.Struct({
|
|
264
|
+
paused: Schema.Boolean
|
|
265
|
+
});
|
|
266
|
+
export const DeleteRecurringExpenseRequest = Schema.Struct({
|
|
267
|
+
confirmed: Schema.Literal(true),
|
|
268
|
+
userIntent: Schema.String.check(Schema.isLengthBetween(1, 500))
|
|
269
|
+
});
|
|
270
|
+
export const DeleteRecurringExpenseResponse = Schema.Struct({
|
|
271
|
+
deleted: Schema.Literal(true),
|
|
272
|
+
recurringExpense: Schema.Struct({
|
|
273
|
+
id: Id,
|
|
274
|
+
description: Schema.String,
|
|
275
|
+
amount: Schema.Number,
|
|
276
|
+
currency: Schema.String,
|
|
277
|
+
frequency: Schema.String,
|
|
278
|
+
groupId: Id
|
|
279
|
+
})
|
|
280
|
+
});
|
|
281
|
+
export const Settlement = Schema.Struct({
|
|
282
|
+
id: Id,
|
|
283
|
+
groupId: Id,
|
|
284
|
+
groupName: NullableString,
|
|
285
|
+
settledBy: Schema.Struct({
|
|
286
|
+
id: Id,
|
|
287
|
+
name: Schema.String
|
|
288
|
+
}),
|
|
289
|
+
settledAt: NullableString,
|
|
290
|
+
expenseCount: Schema.Number,
|
|
291
|
+
totalsByCurrency: Schema.Record(Schema.String, Schema.Number),
|
|
292
|
+
expenses: Schema.Array(Schema.Struct({
|
|
293
|
+
id: Id,
|
|
294
|
+
description: Schema.String,
|
|
295
|
+
amount: Schema.Number,
|
|
296
|
+
currency: Schema.String,
|
|
297
|
+
date: NullableString,
|
|
298
|
+
payerId: NullableString
|
|
299
|
+
}))
|
|
300
|
+
});
|
|
301
|
+
export const ListSettlementsResponse = Schema.Struct({
|
|
302
|
+
currentUserId: Id,
|
|
303
|
+
settlements: Schema.Array(Settlement)
|
|
304
|
+
});
|
|
305
|
+
export const PreviewSettlementRequest = Schema.Struct({
|
|
306
|
+
expenseIds: Schema.Array(Id).check(Schema.isLengthBetween(1, 100)),
|
|
307
|
+
currency: Schema.optionalKey(Currency)
|
|
308
|
+
});
|
|
309
|
+
export const SettlementPayment = Schema.Struct({
|
|
310
|
+
direction: Schema.Literals(["pay", "request"]),
|
|
311
|
+
userId: Id,
|
|
312
|
+
name: Schema.String,
|
|
313
|
+
amount: Schema.String,
|
|
314
|
+
currency: Schema.String,
|
|
315
|
+
venmoUsername: NullableString,
|
|
316
|
+
venmoWebUrl: NullableString,
|
|
317
|
+
venmoProfileUrl: NullableString,
|
|
318
|
+
venmoMarkdownLink: NullableString,
|
|
319
|
+
displayText: Schema.String,
|
|
320
|
+
note: Schema.String
|
|
321
|
+
});
|
|
322
|
+
export const PreviewSettlementResponse = Schema.Struct({
|
|
323
|
+
groupId: Id,
|
|
324
|
+
currency: Schema.String,
|
|
325
|
+
expenseIds: Schema.Array(Id),
|
|
326
|
+
payments: Schema.Array(SettlementPayment)
|
|
327
|
+
});
|
|
328
|
+
export const SettleExpensesRequest = Schema.Struct({
|
|
329
|
+
expenseIds: Schema.Array(Id).check(Schema.isLengthBetween(1, 100)),
|
|
330
|
+
currency: Schema.optionalKey(Currency),
|
|
331
|
+
confirmed: Schema.Literal(true),
|
|
332
|
+
userIntent: Schema.String.check(Schema.isLengthBetween(1, 500))
|
|
333
|
+
});
|
|
334
|
+
export const SettleExpensesResponse = Schema.Struct({
|
|
335
|
+
settlement: Schema.Struct({
|
|
336
|
+
id: Id,
|
|
337
|
+
groupId: Id,
|
|
338
|
+
settledBy: Id,
|
|
339
|
+
settledAt: NullableString,
|
|
340
|
+
expenseIds: Schema.Array(Id)
|
|
341
|
+
}),
|
|
342
|
+
payments: Schema.Array(SettlementPayment)
|
|
343
|
+
});
|
|
344
|
+
export const GetSpendSummaryResponse = Schema.Struct({
|
|
345
|
+
currentUserId: Id,
|
|
346
|
+
currency: Schema.String,
|
|
347
|
+
groupId: NullableString,
|
|
348
|
+
from: NullableString,
|
|
349
|
+
to: NullableString,
|
|
350
|
+
query: NullableString,
|
|
351
|
+
expenseCount: Schema.Number,
|
|
352
|
+
totalSpent: Schema.Number,
|
|
353
|
+
yourPaid: Schema.Number,
|
|
354
|
+
yourShare: Schema.Number,
|
|
355
|
+
byPerson: Schema.Array(Schema.Struct({
|
|
356
|
+
userId: Id,
|
|
357
|
+
name: Schema.String,
|
|
358
|
+
paid: Schema.Number,
|
|
359
|
+
share: Schema.Number
|
|
360
|
+
})),
|
|
361
|
+
byMonth: Schema.Array(Schema.Struct({
|
|
362
|
+
month: Schema.String,
|
|
363
|
+
total: Schema.Number,
|
|
364
|
+
count: Schema.Number
|
|
365
|
+
})),
|
|
366
|
+
byDescription: Schema.Array(Schema.Struct({
|
|
367
|
+
description: Schema.String,
|
|
368
|
+
total: Schema.Number,
|
|
369
|
+
count: Schema.Number
|
|
370
|
+
})),
|
|
371
|
+
byGroup: Schema.Array(Schema.Struct({
|
|
372
|
+
groupId: Id,
|
|
373
|
+
groupName: NullableString,
|
|
374
|
+
total: Schema.Number,
|
|
375
|
+
count: Schema.Number
|
|
376
|
+
}))
|
|
377
|
+
});
|
|
378
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/api/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Context, Crypto, Effect, Layer } from "effect";
|
|
2
|
+
import { CliConfig } from "../config.js";
|
|
3
|
+
import { AuthRequiredError, BrowserOpenError, CliConfigError, CliStorageError, OAuthCallbackError, OAuthRequestError, RefreshLockError } from "../errors.js";
|
|
4
|
+
import { BrowserLauncher } from "./browser.js";
|
|
5
|
+
import { CredentialStore } from "./credential-store.js";
|
|
6
|
+
import { InstallationStore } from "./installation-store.js";
|
|
7
|
+
import { API_READ_SCOPE, API_WRITE_SCOPE } from "./model.js";
|
|
8
|
+
import type { AuthStatus } from "./model.js";
|
|
9
|
+
import { OAuthClient } from "./oauth-client.js";
|
|
10
|
+
import { AuthorizationCallback } from "./oauth-callback.js";
|
|
11
|
+
export type AuthError = AuthRequiredError | CliConfigError | CliStorageError | OAuthCallbackError | OAuthRequestError | RefreshLockError;
|
|
12
|
+
export type LogoutStatus = AuthStatus & {
|
|
13
|
+
readonly revocation: "confirmed" | "unconfirmed" | "not_needed";
|
|
14
|
+
};
|
|
15
|
+
export type LoginStatus = AuthStatus & {
|
|
16
|
+
readonly replacedSessionRevocation?: "confirmed" | "unconfirmed";
|
|
17
|
+
};
|
|
18
|
+
declare const AuthService_base: Context.ServiceClass<AuthService, "@allsquare/cli/AuthService", {
|
|
19
|
+
readonly login: (options: {
|
|
20
|
+
readonly write: boolean;
|
|
21
|
+
readonly noBrowser: boolean;
|
|
22
|
+
readonly onAuthorizationUrl: (url: string) => Effect.Effect<void>;
|
|
23
|
+
readonly onBrowserOpenError: (error: BrowserOpenError) => Effect.Effect<void>;
|
|
24
|
+
}) => Effect.Effect<LoginStatus, AuthError>;
|
|
25
|
+
readonly status: Effect.Effect<AuthStatus, AuthError>;
|
|
26
|
+
readonly logout: Effect.Effect<LogoutStatus, AuthError>;
|
|
27
|
+
readonly refresh: Effect.Effect<AuthStatus, AuthError>;
|
|
28
|
+
readonly accessToken: (requiredScope?: typeof API_READ_SCOPE | typeof API_WRITE_SCOPE) => Effect.Effect<string, AuthError>;
|
|
29
|
+
}>;
|
|
30
|
+
export declare class AuthService extends AuthService_base {
|
|
31
|
+
static readonly layer: Layer.Layer<AuthService, never, CliConfig | BrowserLauncher | CredentialStore | InstallationStore | Crypto.Crypto | OAuthClient | AuthorizationCallback>;
|
|
32
|
+
}
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=auth-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-service.d.ts","sourceRoot":"","sources":["../../src/auth/auth-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAEvD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EACL,cAAc,EACd,eAAe,EAIhB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,UAAU,EAAiC,MAAM,YAAY,CAAA;AAC3E,OAAO,EAAyB,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAG3D,MAAM,MAAM,SAAS,GACjB,iBAAiB,GACjB,cAAc,GACd,eAAe,GACf,kBAAkB,GAClB,iBAAiB,GACjB,gBAAgB,CAAA;AAEpB,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG;IACtC,QAAQ,CAAC,UAAU,EAAE,WAAW,GAAG,aAAa,GAAG,YAAY,CAAA;CAChE,CAAA;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG;IAErC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,WAAW,GAAG,aAAa,CAAA;CACjE,CAAA;;oBAsCiB,CAAC,OAAO,EAAE;QACxB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;QACvB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;QAC3B,QAAQ,CAAC,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACjE,QAAQ,CAAC,kBAAkB,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;KAC9E,KAAK,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC;qBAC1B,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC;qBACpC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC;sBACrC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC;0BAChC,CACpB,aAAa,CAAC,EAAE,OAAO,cAAc,GAAG,OAAO,eAAe,KAC3D,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC;;AAZvC,qBAAa,WAAY,SAAQ,gBAaC;IAChC,MAAM,CAAC,QAAQ,CAAC,KAAK,2JA8PpB;CACF"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { Context, Crypto, Effect, Layer } from "effect";
|
|
2
|
+
import { CliConfig } from "../config.js";
|
|
3
|
+
import { AuthRequiredError, BrowserOpenError, CliConfigError, CliStorageError, OAuthCallbackError, OAuthRequestError, RefreshLockError } from "../errors.js";
|
|
4
|
+
import { BrowserLauncher } from "./browser.js";
|
|
5
|
+
import { CredentialStore } from "./credential-store.js";
|
|
6
|
+
import { InstallationStore } from "./installation-store.js";
|
|
7
|
+
import { API_READ_SCOPE, API_WRITE_SCOPE, Credentials, Installation, REGISTERED_REDIRECT_URI } from "./model.js";
|
|
8
|
+
import { buildAuthorizationUrl, OAuthClient } from "./oauth-client.js";
|
|
9
|
+
import { AuthorizationCallback } from "./oauth-callback.js";
|
|
10
|
+
import { createPkceAuthorization } from "./pkce.js";
|
|
11
|
+
const insufficientScope = (requiredScope) => new AuthRequiredError({
|
|
12
|
+
message: requiredScope === API_WRITE_SCOPE
|
|
13
|
+
? "This session is read-only. Run `allsquare auth login` to grant write access."
|
|
14
|
+
: "Read access is required. Run `allsquare auth login`.",
|
|
15
|
+
reason: "insufficient_scope"
|
|
16
|
+
});
|
|
17
|
+
const credentialsFromToken = (token) => ({
|
|
18
|
+
accessToken: token.accessToken,
|
|
19
|
+
refreshToken: token.refreshToken,
|
|
20
|
+
tokenType: token.tokenType,
|
|
21
|
+
expiresAt: Date.now() + token.expiresIn * 1_000,
|
|
22
|
+
scopes: [...token.scopes]
|
|
23
|
+
});
|
|
24
|
+
const statusFrom = (apiUrl, installation, credentials) => {
|
|
25
|
+
if (!installation || !credentials) {
|
|
26
|
+
return { authenticated: false, apiUrl };
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
authenticated: true,
|
|
30
|
+
apiUrl,
|
|
31
|
+
clientId: installation.clientId,
|
|
32
|
+
scopes: credentials.scopes,
|
|
33
|
+
expiresAt: new Date(credentials.expiresAt).toISOString()
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export class AuthService extends Context.Service()("@allsquare/cli/AuthService") {
|
|
37
|
+
static layer = Layer.effect(AuthService, Effect.gen(function* () {
|
|
38
|
+
const config = yield* CliConfig;
|
|
39
|
+
const installations = yield* InstallationStore;
|
|
40
|
+
const credentialStore = yield* CredentialStore;
|
|
41
|
+
const oauth = yield* OAuthClient;
|
|
42
|
+
const callback = yield* AuthorizationCallback;
|
|
43
|
+
const browser = yield* BrowserLauncher;
|
|
44
|
+
const crypto = yield* Crypto.Crypto;
|
|
45
|
+
const resource = config.apiUrl;
|
|
46
|
+
const getOrRegisterInstallation = (apiUrl, endpoints) => installations.withAuthLock(Effect.gen(function* () {
|
|
47
|
+
const existing = yield* installations.load(apiUrl);
|
|
48
|
+
if (existing)
|
|
49
|
+
return existing;
|
|
50
|
+
const installationId = yield* crypto.randomUUIDv4.pipe(Effect.mapError((cause) => new OAuthRequestError({
|
|
51
|
+
message: `Could not create an installation identifier: ${cause.message}`
|
|
52
|
+
})));
|
|
53
|
+
const clientId = yield* oauth.register({
|
|
54
|
+
endpoints,
|
|
55
|
+
name: `AllSquare CLI (${installationId.slice(0, 8)})`,
|
|
56
|
+
redirectUri: REGISTERED_REDIRECT_URI
|
|
57
|
+
});
|
|
58
|
+
const installation = {
|
|
59
|
+
installationId,
|
|
60
|
+
clientId,
|
|
61
|
+
resource: endpoints.resource,
|
|
62
|
+
registeredRedirectUri: REGISTERED_REDIRECT_URI,
|
|
63
|
+
registeredAt: new Date().toISOString()
|
|
64
|
+
};
|
|
65
|
+
yield* installations.save(installation);
|
|
66
|
+
return installation;
|
|
67
|
+
}));
|
|
68
|
+
const invalidateRotatedSession = (apiUrl, error) => {
|
|
69
|
+
if (error.oauthError !== "invalid_grant")
|
|
70
|
+
return Effect.fail(error);
|
|
71
|
+
return credentialStore.remove(apiUrl).pipe(Effect.andThen(Effect.fail(new AuthRequiredError({
|
|
72
|
+
message: "Your session can no longer be refreshed. Run `allsquare auth login` again."
|
|
73
|
+
}))));
|
|
74
|
+
};
|
|
75
|
+
// The server revokes exactly the token it is given, so revoking an old
|
|
76
|
+
// session cannot affect a session issued by a later authorization.
|
|
77
|
+
const revokeCredentials = (endpoints, clientId, credentials) => oauth.revoke({ endpoints, clientId, token: credentials.refreshToken }).pipe(Effect.andThen(oauth.revoke({ endpoints, clientId, token: credentials.accessToken })));
|
|
78
|
+
const refreshCredentials = (apiUrl, force, requiredScope) => installations.withAuthLock(Effect.gen(function* () {
|
|
79
|
+
// Always reload after acquiring the cross-process lock. Another CLI
|
|
80
|
+
// process may have rotated and saved the refresh token while this
|
|
81
|
+
// process was waiting.
|
|
82
|
+
const current = yield* credentialStore.load(apiUrl);
|
|
83
|
+
if (!current) {
|
|
84
|
+
return yield* new AuthRequiredError({
|
|
85
|
+
message: "You are not logged in. Run `allsquare auth login`."
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
// Check scope before refreshing: a failed refresh deletes the
|
|
89
|
+
// session and would hide that it was deliberately read-only.
|
|
90
|
+
if (requiredScope && !current.scopes.includes(requiredScope)) {
|
|
91
|
+
return yield* insufficientScope(requiredScope);
|
|
92
|
+
}
|
|
93
|
+
if (!force && current.expiresAt > Date.now() + 60_000)
|
|
94
|
+
return current;
|
|
95
|
+
const installation = yield* installations.load(apiUrl);
|
|
96
|
+
if (!installation) {
|
|
97
|
+
return yield* new AuthRequiredError({
|
|
98
|
+
message: "This CLI installation is not registered. Run `allsquare auth login`."
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const endpoints = yield* oauth.discover(apiUrl);
|
|
102
|
+
const token = yield* oauth.refresh({
|
|
103
|
+
endpoints,
|
|
104
|
+
clientId: installation.clientId,
|
|
105
|
+
refreshToken: current.refreshToken
|
|
106
|
+
}).pipe(Effect.catchTag("OAuthRequestError", (error) => invalidateRotatedSession(apiUrl, error)));
|
|
107
|
+
const next = credentialsFromToken(token);
|
|
108
|
+
yield* credentialStore.save(apiUrl, next);
|
|
109
|
+
return next;
|
|
110
|
+
}));
|
|
111
|
+
const status = Effect.gen(function* () {
|
|
112
|
+
const apiUrl = yield* resource;
|
|
113
|
+
const [installation, credentials] = yield* Effect.all([
|
|
114
|
+
installations.load(apiUrl),
|
|
115
|
+
credentialStore.load(apiUrl)
|
|
116
|
+
]);
|
|
117
|
+
return statusFrom(apiUrl, installation, credentials);
|
|
118
|
+
});
|
|
119
|
+
return AuthService.of({
|
|
120
|
+
login: ({ write, noBrowser, onAuthorizationUrl, onBrowserOpenError }) => Effect.gen(function* () {
|
|
121
|
+
const apiUrl = yield* resource;
|
|
122
|
+
const endpoints = yield* oauth.discover(apiUrl);
|
|
123
|
+
const installation = yield* getOrRegisterInstallation(apiUrl, endpoints);
|
|
124
|
+
const pkce = yield* createPkceAuthorization.pipe(Effect.provideService(Crypto.Crypto, crypto));
|
|
125
|
+
const scopes = write
|
|
126
|
+
? [API_READ_SCOPE, API_WRITE_SCOPE]
|
|
127
|
+
: [API_READ_SCOPE];
|
|
128
|
+
let redirectUri = "";
|
|
129
|
+
const code = yield* callback.receive({
|
|
130
|
+
state: pkce.state,
|
|
131
|
+
onReady: (callbackUri) => {
|
|
132
|
+
redirectUri = callbackUri;
|
|
133
|
+
const authorizationUrl = buildAuthorizationUrl({
|
|
134
|
+
endpoint: endpoints.authorizationEndpoint,
|
|
135
|
+
clientId: installation.clientId,
|
|
136
|
+
redirectUri: callbackUri,
|
|
137
|
+
resource: endpoints.resource,
|
|
138
|
+
scopes,
|
|
139
|
+
state: pkce.state,
|
|
140
|
+
challenge: pkce.challenge
|
|
141
|
+
});
|
|
142
|
+
return onAuthorizationUrl(authorizationUrl).pipe(Effect.andThen(noBrowser
|
|
143
|
+
? Effect.void
|
|
144
|
+
: browser.open(authorizationUrl).pipe(Effect.catchTag("BrowserOpenError", onBrowserOpenError))));
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
const token = yield* oauth.exchangeCode({
|
|
148
|
+
endpoints,
|
|
149
|
+
clientId: installation.clientId,
|
|
150
|
+
code,
|
|
151
|
+
verifier: pkce.verifier,
|
|
152
|
+
redirectUri
|
|
153
|
+
});
|
|
154
|
+
if (scopes.some((scope) => !token.scopes.includes(scope))) {
|
|
155
|
+
return yield* new OAuthRequestError({
|
|
156
|
+
message: "The authorization server did not grant all requested scopes."
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
const credentials = credentialsFromToken(token);
|
|
160
|
+
const replaced = yield* installations.withAuthLock(Effect.gen(function* () {
|
|
161
|
+
const previous = yield* Effect.result(credentialStore.load(apiUrl));
|
|
162
|
+
yield* credentialStore.save(apiUrl, credentials);
|
|
163
|
+
return previous._tag === "Success" ? previous.success : undefined;
|
|
164
|
+
}));
|
|
165
|
+
const status = statusFrom(apiUrl, installation, credentials);
|
|
166
|
+
if (!replaced || replaced.refreshToken === credentials.refreshToken)
|
|
167
|
+
return status;
|
|
168
|
+
// A login replaces the earlier grant rather than narrowing it, so
|
|
169
|
+
// revoke the old tokens; otherwise --read-only would leave
|
|
170
|
+
// previously issued write access valid on the server.
|
|
171
|
+
const revocation = yield* Effect.result(revokeCredentials(endpoints, installation.clientId, replaced));
|
|
172
|
+
return {
|
|
173
|
+
...status,
|
|
174
|
+
replacedSessionRevocation: revocation._tag === "Success"
|
|
175
|
+
? "confirmed"
|
|
176
|
+
: "unconfirmed"
|
|
177
|
+
};
|
|
178
|
+
}),
|
|
179
|
+
status,
|
|
180
|
+
logout: Effect.gen(function* () {
|
|
181
|
+
const apiUrl = yield* resource;
|
|
182
|
+
return yield* installations.withAuthLock(Effect.gen(function* () {
|
|
183
|
+
const credentials = yield* credentialStore.load(apiUrl);
|
|
184
|
+
// Broken registration metadata must not strand a local token.
|
|
185
|
+
const installationLookup = yield* Effect.result(installations.load(apiUrl));
|
|
186
|
+
const installation = installationLookup._tag === "Success"
|
|
187
|
+
? installationLookup.success
|
|
188
|
+
: undefined;
|
|
189
|
+
if (!credentials) {
|
|
190
|
+
return { ...statusFrom(apiUrl, installation, undefined), revocation: "not_needed" };
|
|
191
|
+
}
|
|
192
|
+
const revocation = installation
|
|
193
|
+
? yield* oauth.discover(apiUrl).pipe(Effect.flatMap((endpoints) => revokeCredentials(endpoints, installation.clientId, credentials)), Effect.result)
|
|
194
|
+
: undefined;
|
|
195
|
+
// Local logout must not depend on the authorization server being
|
|
196
|
+
// reachable. An unconfirmed revocation is reported to the user.
|
|
197
|
+
yield* credentialStore.remove(apiUrl);
|
|
198
|
+
return {
|
|
199
|
+
...statusFrom(apiUrl, installation, undefined),
|
|
200
|
+
revocation: revocation?._tag === "Success" ? "confirmed" : "unconfirmed"
|
|
201
|
+
};
|
|
202
|
+
}));
|
|
203
|
+
}),
|
|
204
|
+
refresh: Effect.gen(function* () {
|
|
205
|
+
const apiUrl = yield* resource;
|
|
206
|
+
const credentials = yield* refreshCredentials(apiUrl, true);
|
|
207
|
+
const installation = yield* installations.load(apiUrl);
|
|
208
|
+
return statusFrom(apiUrl, installation, credentials);
|
|
209
|
+
}),
|
|
210
|
+
accessToken: (requiredScope = API_READ_SCOPE) => Effect.gen(function* () {
|
|
211
|
+
const apiUrl = yield* resource;
|
|
212
|
+
const credentials = yield* refreshCredentials(apiUrl, false, requiredScope);
|
|
213
|
+
if (!credentials.scopes.includes(requiredScope)) {
|
|
214
|
+
return yield* insufficientScope(requiredScope);
|
|
215
|
+
}
|
|
216
|
+
return credentials.accessToken;
|
|
217
|
+
})
|
|
218
|
+
});
|
|
219
|
+
}));
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=auth-service.js.map
|