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.
Files changed (132) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +234 -0
  4. package/dist/api/client.d.ts +46 -0
  5. package/dist/api/client.d.ts.map +1 -0
  6. package/dist/api/client.js +162 -0
  7. package/dist/api/client.js.map +1 -0
  8. package/dist/api/contract.d.ts +549 -0
  9. package/dist/api/contract.d.ts.map +1 -0
  10. package/dist/api/contract.js +49 -0
  11. package/dist/api/contract.js.map +1 -0
  12. package/dist/api/model.d.ts +627 -0
  13. package/dist/api/model.d.ts.map +1 -0
  14. package/dist/api/model.js +378 -0
  15. package/dist/api/model.js.map +1 -0
  16. package/dist/auth/auth-service.d.ts +34 -0
  17. package/dist/auth/auth-service.d.ts.map +1 -0
  18. package/dist/auth/auth-service.js +221 -0
  19. package/dist/auth/auth-service.js.map +1 -0
  20. package/dist/auth/browser.d.ts +12 -0
  21. package/dist/auth/browser.d.ts.map +1 -0
  22. package/dist/auth/browser.js +50 -0
  23. package/dist/auth/browser.js.map +1 -0
  24. package/dist/auth/credential-store.d.ts +28 -0
  25. package/dist/auth/credential-store.d.ts.map +1 -0
  26. package/dist/auth/credential-store.js +75 -0
  27. package/dist/auth/credential-store.js.map +1 -0
  28. package/dist/auth/installation-store.d.ts +14 -0
  29. package/dist/auth/installation-store.d.ts.map +1 -0
  30. package/dist/auth/installation-store.js +122 -0
  31. package/dist/auth/installation-store.js.map +1 -0
  32. package/dist/auth/model.d.ts +54 -0
  33. package/dist/auth/model.d.ts.map +1 -0
  34. package/dist/auth/model.js +24 -0
  35. package/dist/auth/model.js.map +1 -0
  36. package/dist/auth/oauth-callback.d.ts +17 -0
  37. package/dist/auth/oauth-callback.d.ts.map +1 -0
  38. package/dist/auth/oauth-callback.js +94 -0
  39. package/dist/auth/oauth-callback.js.map +1 -0
  40. package/dist/auth/oauth-client.d.ts +43 -0
  41. package/dist/auth/oauth-client.d.ts.map +1 -0
  42. package/dist/auth/oauth-client.js +191 -0
  43. package/dist/auth/oauth-client.js.map +1 -0
  44. package/dist/auth/pkce.d.ts +9 -0
  45. package/dist/auth/pkce.d.ts.map +1 -0
  46. package/dist/auth/pkce.js +12 -0
  47. package/dist/auth/pkce.js.map +1 -0
  48. package/dist/command.d.ts +3 -0
  49. package/dist/command.d.ts.map +1 -0
  50. package/dist/command.js +24 -0
  51. package/dist/command.js.map +1 -0
  52. package/dist/commands/agent-guide.d.ts +5 -0
  53. package/dist/commands/agent-guide.d.ts.map +1 -0
  54. package/dist/commands/agent-guide.js +226 -0
  55. package/dist/commands/agent-guide.js.map +1 -0
  56. package/dist/commands/auth.d.ts +5 -0
  57. package/dist/commands/auth.d.ts.map +1 -0
  58. package/dist/commands/auth.js +68 -0
  59. package/dist/commands/auth.js.map +1 -0
  60. package/dist/commands/balances.d.ts +5 -0
  61. package/dist/commands/balances.d.ts.map +1 -0
  62. package/dist/commands/balances.js +106 -0
  63. package/dist/commands/balances.js.map +1 -0
  64. package/dist/commands/config.d.ts +4 -0
  65. package/dist/commands/config.d.ts.map +1 -0
  66. package/dist/commands/config.js +16 -0
  67. package/dist/commands/config.js.map +1 -0
  68. package/dist/commands/expense-input.d.ts +17 -0
  69. package/dist/commands/expense-input.d.ts.map +1 -0
  70. package/dist/commands/expense-input.js +78 -0
  71. package/dist/commands/expense-input.js.map +1 -0
  72. package/dist/commands/expenses.d.ts +5 -0
  73. package/dist/commands/expenses.d.ts.map +1 -0
  74. package/dist/commands/expenses.js +419 -0
  75. package/dist/commands/expenses.js.map +1 -0
  76. package/dist/commands/groups.d.ts +5 -0
  77. package/dist/commands/groups.d.ts.map +1 -0
  78. package/dist/commands/groups.js +149 -0
  79. package/dist/commands/groups.js.map +1 -0
  80. package/dist/commands/recurring-expenses.d.ts +5 -0
  81. package/dist/commands/recurring-expenses.d.ts.map +1 -0
  82. package/dist/commands/recurring-expenses.js +416 -0
  83. package/dist/commands/recurring-expenses.js.map +1 -0
  84. package/dist/commands/settlements.d.ts +5 -0
  85. package/dist/commands/settlements.d.ts.map +1 -0
  86. package/dist/commands/settlements.js +225 -0
  87. package/dist/commands/settlements.js.map +1 -0
  88. package/dist/commands/shared.d.ts +6 -0
  89. package/dist/commands/shared.d.ts.map +1 -0
  90. package/dist/commands/shared.js +35 -0
  91. package/dist/commands/shared.js.map +1 -0
  92. package/dist/commands/spend-summary.d.ts +5 -0
  93. package/dist/commands/spend-summary.d.ts.map +1 -0
  94. package/dist/commands/spend-summary.js +107 -0
  95. package/dist/commands/spend-summary.js.map +1 -0
  96. package/dist/commands/update.d.ts +9 -0
  97. package/dist/commands/update.d.ts.map +1 -0
  98. package/dist/commands/update.js +78 -0
  99. package/dist/commands/update.js.map +1 -0
  100. package/dist/config.d.ts +14 -0
  101. package/dist/config.d.ts.map +1 -0
  102. package/dist/config.js +52 -0
  103. package/dist/config.js.map +1 -0
  104. package/dist/errors.d.ts +87 -0
  105. package/dist/errors.d.ts.map +1 -0
  106. package/dist/errors.js +183 -0
  107. package/dist/errors.js.map +1 -0
  108. package/dist/index.d.ts +3 -0
  109. package/dist/index.d.ts.map +1 -0
  110. package/dist/index.js +43 -0
  111. package/dist/index.js.map +1 -0
  112. package/dist/interaction.d.ts +16 -0
  113. package/dist/interaction.d.ts.map +1 -0
  114. package/dist/interaction.js +14 -0
  115. package/dist/interaction.js.map +1 -0
  116. package/dist/layers.d.ts +13 -0
  117. package/dist/layers.d.ts.map +1 -0
  118. package/dist/layers.js +17 -0
  119. package/dist/layers.js.map +1 -0
  120. package/dist/output.d.ts +31 -0
  121. package/dist/output.d.ts.map +1 -0
  122. package/dist/output.js +26 -0
  123. package/dist/output.js.map +1 -0
  124. package/dist/update/update-service.d.ts +41 -0
  125. package/dist/update/update-service.d.ts.map +1 -0
  126. package/dist/update/update-service.js +231 -0
  127. package/dist/update/update-service.js.map +1 -0
  128. package/dist/version.d.ts +3 -0
  129. package/dist/version.d.ts.map +1 -0
  130. package/dist/version.js +3 -0
  131. package/dist/version.js.map +1 -0
  132. package/package.json +41 -0
@@ -0,0 +1,225 @@
1
+ import { Console, Effect, Option } from "effect";
2
+ import { Argument, Command, Flag, Prompt } from "effect/unstable/cli";
3
+ import { ApiClient } from "../api/client.js";
4
+ import { ListSettlementsResponse, PreviewSettlementRequest, PreviewSettlementResponse, SettleExpensesRequest, SettleExpensesResponse } from "../api/model.js";
5
+ import { API_READ_SCOPE, API_WRITE_SCOPE } from "../auth/model.js";
6
+ import { CliInputError } from "../errors.js";
7
+ import { formatTable, printSuccess } from "../output.js";
8
+ import { failInput, parseOptionalCurrency, validateIdempotencyKey } from "./expense-input.js";
9
+ import { jsonFlag, reportFailure } from "./shared.js";
10
+ const groupIdFlag = Flag.String("group-id").pipe(Flag.withMetavar("ID"), Flag.withDescription("Only include settlements from this group"), Flag.optional);
11
+ const limitFlag = Flag.Int("limit").pipe(Flag.withMetavar("COUNT"), Flag.withDescription("Return 1 to 50 settlements (default: 20)"), Flag.optional);
12
+ const expenseIdsFlag = Flag.String("expense-id").pipe(Flag.withMetavar("ID"), Flag.withDescription("Expense to include; repeat for multiple expenses"), Flag.between(1, 100));
13
+ const currencyFlag = Flag.String("currency").pipe(Flag.withMetavar("CODE"), Flag.withDescription("Settlement currency: USD, CAD, EUR, or GBP"), Flag.optional);
14
+ const yesFlag = Flag.Boolean("yes").pipe(Flag.withDescription("Confirm settlement without an interactive prompt"), Flag.withDefault(false));
15
+ const idempotencyKeyFlag = Flag.String("idempotency-key").pipe(Flag.withMetavar("KEY"), Flag.withDescription("Reuse a stable key when retrying the same settlement"), Flag.optional);
16
+ const normalizeCurrency = parseOptionalCurrency;
17
+ const validateExpenseIds = (expenseIds) => new Set(expenseIds).size === expenseIds.length
18
+ ? Effect.void
19
+ : failInput("expense IDs must not contain duplicates");
20
+ const totals = (values) => Object.entries(values)
21
+ .sort(([left], [right]) => left.localeCompare(right))
22
+ .map(([currency, amount]) => `${amount} ${currency}`)
23
+ .join(", ") || "—";
24
+ const renderSettlements = (response) => {
25
+ if (response.settlements.length === 0)
26
+ return "No settlements found.";
27
+ const summary = formatTable(["ID", "SETTLED AT", "GROUP", "SETTLED BY", "EXPENSES", "TOTALS"], response.settlements.map((settlement) => [
28
+ settlement.id,
29
+ settlement.settledAt ?? "—",
30
+ settlement.groupName ?? settlement.groupId,
31
+ settlement.settledBy.name,
32
+ String(settlement.expenseCount),
33
+ totals(settlement.totalsByCurrency)
34
+ ]));
35
+ const expenses = response.settlements.flatMap((settlement) => settlement.expenses.map((expense) => [
36
+ settlement.id,
37
+ expense.id,
38
+ expense.date ?? "—",
39
+ expense.description,
40
+ `${expense.amount} ${expense.currency}`
41
+ ]));
42
+ return expenses.length === 0
43
+ ? summary
44
+ : `${summary}\n\nExpenses\n${formatTable(["SETTLEMENT", "EXPENSE", "DATE", "DESCRIPTION", "AMOUNT"], expenses)}`;
45
+ };
46
+ // The API's displayText is Markdown for chat clients (escaped names, link
47
+ // syntax). A terminal builds plain text from the structured fields instead,
48
+ // then lists each Venmo URL on its own line.
49
+ const plainInstruction = (payment) => {
50
+ const action = payment.direction === "pay"
51
+ ? `Pay ${payment.name} ${payment.amount} ${payment.currency}`
52
+ : `Request ${payment.amount} ${payment.currency} from ${payment.name}`;
53
+ return payment.venmoWebUrl === null
54
+ ? `${action}. No Venmo username is saved in AllSquare.`
55
+ : `${action} (Venmo link below)`;
56
+ };
57
+ const renderPayments = (payments) => {
58
+ const table = formatTable(["DIRECTION", "PERSON", "AMOUNT", "INSTRUCTION"], payments.map((payment) => [
59
+ payment.direction,
60
+ payment.name,
61
+ `${payment.amount} ${payment.currency}`,
62
+ plainInstruction(payment)
63
+ ]));
64
+ const links = payments.flatMap((payment) => payment.venmoWebUrl === null ? [] : [`Venmo (${payment.name}): ${payment.venmoWebUrl}`]);
65
+ return links.length === 0 ? table : `${table}\n\n${links.join("\n")}`;
66
+ };
67
+ const renderPreview = (response) => {
68
+ const heading = [
69
+ `Group: ${response.groupId}`,
70
+ `Currency: ${response.currency}`,
71
+ `Expenses: ${response.expenseIds.join(", ")}`
72
+ ].join("\n");
73
+ if (response.payments.length === 0)
74
+ return `${heading}\n\nNo payments needed.`;
75
+ return `${heading}\n\n${renderPayments(response.payments)}`;
76
+ };
77
+ const renderSettlement = (response) => {
78
+ const { settlement } = response;
79
+ const heading = [
80
+ `Settlement: ${settlement.id}`,
81
+ `Group: ${settlement.groupId}`,
82
+ `Settled by: ${settlement.settledBy}`,
83
+ `Settled at: ${settlement.settledAt ?? "—"}`,
84
+ `Expenses: ${settlement.expenseIds.join(", ")}`,
85
+ "No money was transferred."
86
+ ].join("\n");
87
+ if (response.payments.length === 0)
88
+ return `${heading}\n\nNo payments needed.`;
89
+ return `${heading}\n\n${renderPayments(response.payments)}`;
90
+ };
91
+ const list = Command.make("list", {
92
+ groupId: groupIdFlag,
93
+ limit: limitFlag,
94
+ json: jsonFlag
95
+ }, Effect.fn(function* ({ groupId, limit, json }) {
96
+ const pageSize = Option.getOrUndefined(limit);
97
+ if (pageSize !== undefined && (pageSize < 1 || pageSize > 50)) {
98
+ return yield* reportFailure(Effect.fail(new CliInputError({
99
+ message: "limit must be between 1 and 50"
100
+ })), json);
101
+ }
102
+ const api = yield* ApiClient;
103
+ const response = yield* reportFailure(api.get({
104
+ path: "/settlements",
105
+ query: {
106
+ groupId: Option.getOrUndefined(groupId),
107
+ limit: pageSize === undefined ? undefined : String(pageSize)
108
+ },
109
+ schema: ListSettlementsResponse
110
+ }), json);
111
+ yield* printSuccess({
112
+ data: response,
113
+ json,
114
+ renderHuman: renderSettlements
115
+ });
116
+ })).pipe(Command.withDescription("List recorded settlements"));
117
+ const preview = Command.make("preview", {
118
+ groupId: Argument.String("group-id").pipe(Argument.withDescription("Group containing the expenses")),
119
+ expenseIds: expenseIdsFlag,
120
+ currency: currencyFlag,
121
+ json: jsonFlag
122
+ }, Effect.fn(function* ({ groupId, expenseIds, currency, json }) {
123
+ const requestedCurrency = yield* reportFailure(normalizeCurrency(currency), json);
124
+ yield* reportFailure(validateExpenseIds(expenseIds), json);
125
+ const api = yield* ApiClient;
126
+ const { data: response } = yield* reportFailure(api.post({
127
+ path: `/groups/${encodeURIComponent(groupId)}/settlements/preview`,
128
+ scope: API_READ_SCOPE,
129
+ body: {
130
+ expenseIds: [...expenseIds],
131
+ ...(requestedCurrency === undefined
132
+ ? {}
133
+ : { currency: requestedCurrency })
134
+ },
135
+ bodySchema: PreviewSettlementRequest,
136
+ schema: PreviewSettlementResponse
137
+ }), json);
138
+ yield* printSuccess({
139
+ data: response,
140
+ json,
141
+ renderHuman: renderPreview
142
+ });
143
+ })).pipe(Command.withDescription("Preview settlement payments without changing data"));
144
+ const settle = Command.make("settle", {
145
+ groupId: Argument.String("group-id").pipe(Argument.withDescription("Group containing the expenses")),
146
+ expenseIds: expenseIdsFlag,
147
+ currency: currencyFlag,
148
+ yes: yesFlag,
149
+ idempotencyKey: idempotencyKeyFlag,
150
+ json: jsonFlag
151
+ }, Effect.fn(function* ({ groupId, expenseIds, currency, yes, idempotencyKey, json }) {
152
+ const requestedCurrency = yield* reportFailure(normalizeCurrency(currency), json);
153
+ yield* reportFailure(validateExpenseIds(expenseIds), json);
154
+ if (!yes && (json || !process.stdin.isTTY)) {
155
+ return yield* reportFailure(failInput("settlement execution requires --yes in non-interactive mode"), json);
156
+ }
157
+ const suppliedKey = Option.getOrUndefined(idempotencyKey);
158
+ yield* reportFailure(validateIdempotencyKey(suppliedKey), json);
159
+ const api = yield* ApiClient;
160
+ const previewResult = yield* Effect.result(api.post({
161
+ path: `/groups/${encodeURIComponent(groupId)}/settlements/preview`,
162
+ scope: API_READ_SCOPE,
163
+ body: {
164
+ expenseIds: [...expenseIds],
165
+ ...(requestedCurrency === undefined
166
+ ? {}
167
+ : { currency: requestedCurrency })
168
+ },
169
+ bodySchema: PreviewSettlementRequest,
170
+ schema: PreviewSettlementResponse
171
+ }));
172
+ // A retry after a lost response finds the expenses already settled, so
173
+ // the preview conflicts. With the original idempotency key, send the settle
174
+ // request anyway: the server returns the original settlement for that key,
175
+ // or rejects the request if these expenses were settled some other way.
176
+ const retryingSettledRequest = previewResult._tag === "Failure" &&
177
+ suppliedKey !== undefined &&
178
+ previewResult.failure._tag === "ApiRequestError" &&
179
+ previewResult.failure.status === 409;
180
+ if (previewResult._tag === "Failure" && !retryingSettledRequest) {
181
+ return yield* reportFailure(Effect.fail(previewResult.failure), json);
182
+ }
183
+ const previewResponse = previewResult._tag === "Success"
184
+ ? previewResult.success.data
185
+ : undefined;
186
+ if (!json && previewResponse !== undefined) {
187
+ yield* Console.log(`Settlement preview:\n${renderPreview(previewResponse)}`);
188
+ }
189
+ if (!yes && previewResponse !== undefined) {
190
+ const confirmed = yield* Prompt.run(Prompt.Confirm({
191
+ message: `Record this settlement and mark ${previewResponse.expenseIds.length} expenses settled? No money will be transferred.`,
192
+ initial: false
193
+ }));
194
+ if (!confirmed) {
195
+ yield* Console.log("Settlement cancelled.");
196
+ return;
197
+ }
198
+ }
199
+ // Build the request from the user's input only, so a retry with the same
200
+ // idempotency key sends an identical request. Without --currency the
201
+ // server settles in the group's default currency, as the preview did.
202
+ const { data: response, replayed } = yield* reportFailure(api.post({
203
+ path: `/groups/${encodeURIComponent(groupId)}/settlements`,
204
+ scope: API_WRITE_SCOPE,
205
+ body: {
206
+ expenseIds: [...expenseIds],
207
+ ...(requestedCurrency === undefined
208
+ ? {}
209
+ : { currency: requestedCurrency }),
210
+ confirmed: true,
211
+ userIntent: "Settle selected expenses via AllSquare CLI after explicit confirmation"
212
+ },
213
+ bodySchema: SettleExpensesRequest,
214
+ schema: SettleExpensesResponse,
215
+ ...(suppliedKey === undefined ? {} : { idempotencyKey: suppliedKey })
216
+ }), json);
217
+ yield* printSuccess({
218
+ data: response,
219
+ replayed,
220
+ json,
221
+ renderHuman: renderSettlement
222
+ });
223
+ })).pipe(Command.withDescription("Preview, confirm, and mark selected expenses settled without transferring money"));
224
+ export const settlementsCommand = Command.make("settlements").pipe(Command.withDescription("Inspect, preview, and record settlements"), Command.withSubcommands([list, preview, settle]));
225
+ //# sourceMappingURL=settlements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settlements.js","sourceRoot":"","sources":["../../src/commands/settlements.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Effect } from "effect";
2
+ import { Flag } from "effect/unstable/cli";
3
+ import type { CliExpectedError } from "../errors.js";
4
+ export declare const jsonFlag: Flag.Flag<boolean>;
5
+ export declare const reportFailure: <A, E extends CliExpectedError, R>(effect: Effect.Effect<A, E, R>, json: boolean) => Effect.Effect<A, E, R>;
6
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/commands/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAE1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAIpD,eAAO,MAAM,QAAQ,oBAGpB,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,CAAC,SAAS,gBAAgB,EAAE,CAAC,EAC5D,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,MAAM,OAAO,KACZ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CA8BpB,CAAA"}
@@ -0,0 +1,35 @@
1
+ import { Effect } from "effect";
2
+ import { Flag } from "effect/unstable/cli";
3
+ import { cliErrorCode, isRetryable } from "../errors.js";
4
+ import { printFailure } from "../output.js";
5
+ export const jsonFlag = Flag.Boolean("json").pipe(Flag.withDescription("Print machine-readable JSON"), Flag.withDefault(false));
6
+ export const reportFailure = (effect, json) => Effect.tapError(effect, (error) => {
7
+ const details = error._tag === "ApiRequestError"
8
+ ? {
9
+ ...(error.status === undefined ? {} : { status: error.status }),
10
+ ...(error.apiCode === undefined ? {} : { apiCode: error.apiCode }),
11
+ ...(error.fields === undefined ? {} : { fields: error.fields }),
12
+ ...(error.route === undefined ? {} : { route: error.route }),
13
+ ...(error.retryAfterSeconds === undefined
14
+ ? {}
15
+ : { retryAfterSeconds: error.retryAfterSeconds })
16
+ }
17
+ : error._tag === "UpdateError"
18
+ ? {
19
+ ...(error.command === undefined ? {} : { command: error.command }),
20
+ ...(error.exitCode === undefined
21
+ ? {}
22
+ : { exitCode: error.exitCode })
23
+ }
24
+ : undefined;
25
+ return printFailure({
26
+ code: cliErrorCode(error),
27
+ message: error.message,
28
+ retryable: isRetryable(error),
29
+ ...(details === undefined || Object.keys(details).length === 0
30
+ ? {}
31
+ : { details }),
32
+ json
33
+ });
34
+ });
35
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/commands/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAG1C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAC/C,IAAI,CAAC,eAAe,CAAC,6BAA6B,CAAC,EACnD,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CACxB,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAA8B,EAC9B,IAAa,EACW,EAAE,CAC1B,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;IAChC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,iBAAiB;QAC9C,CAAC,CAAC;YACE,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;YAC/D,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;YAClE,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;YAC/D,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5D,GAAG,CAAC,KAAK,CAAC,iBAAiB,KAAK,SAAS;gBACvC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC;SACpD;QACH,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa;YAC5B,CAAC,CAAC;gBACE,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;gBAClE,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS;oBAC9B,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;aAClC;YACH,CAAC,CAAC,SAAS,CAAA;IAEf,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC;QACzB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,SAAS,EAAE,WAAW,CAAC,KAAK,CAAC;QAC7B,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC;YAC5D,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;QAChB,IAAI;KACL,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ import { Command } from "effect/unstable/cli";
2
+ import { ApiClient } from "../api/client.js";
3
+ import { CliInputError } from "../errors.js";
4
+ export declare const spendSummaryCommand: Command.Command<"spend-summary", {}, {}, CliInputError | import("../api/client.js").ApiClientError, ApiClient>;
5
+ //# sourceMappingURL=spend-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spend-summary.d.ts","sourceRoot":"","sources":["../../src/commands/spend-summary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAQ,MAAM,qBAAqB,CAAA;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAG5C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AA4K5C,eAAO,MAAM,mBAAmB,gHAG/B,CAAA"}
@@ -0,0 +1,107 @@
1
+ import { Effect, Option } from "effect";
2
+ import { Command, Flag } from "effect/unstable/cli";
3
+ import { ApiClient } from "../api/client.js";
4
+ import { GetSpendSummaryResponse } from "../api/model.js";
5
+ import { CliInputError } from "../errors.js";
6
+ import { formatTable, printSuccess } from "../output.js";
7
+ import { isCurrency } from "./expense-input.js";
8
+ import { jsonFlag, reportFailure } from "./shared.js";
9
+ const optionalStringFlag = (name, metavar, description) => Flag.String(name).pipe(Flag.withMetavar(metavar), Flag.withDescription(description), Flag.optional);
10
+ const groupIdFlag = optionalStringFlag("group-id", "ID", "Only summarize expenses from this group");
11
+ const fromFlag = optionalStringFlag("from", "YYYY-MM-DD", "Include expenses on or after this date");
12
+ const toFlag = optionalStringFlag("to", "YYYY-MM-DD", "Include expenses on or before this date");
13
+ const queryFlag = optionalStringFlag("query", "TEXT", "Match expense descriptions (maximum 200 characters)");
14
+ const currencyFlag = Flag.String("currency").pipe(Flag.withMetavar("CODE"), Flag.withDescription("Report totals in USD, CAD, EUR, or GBP"), Flag.map((currency) => currency.toUpperCase()), Flag.optional);
15
+ const inputFailure = (message) => Effect.fail(new CliInputError({ message }));
16
+ const validateSummaryQuery = (filters) => Effect.gen(function* () {
17
+ const groupId = Option.getOrUndefined(filters.groupId);
18
+ const from = Option.getOrUndefined(filters.from);
19
+ const to = Option.getOrUndefined(filters.to);
20
+ const query = Option.getOrUndefined(filters.query);
21
+ const currency = Option.getOrUndefined(filters.currency);
22
+ if (groupId === "")
23
+ return yield* inputFailure("group ID must not be empty");
24
+ if (from !== undefined && !/^\d{4}-\d{2}-\d{2}$/.test(from)) {
25
+ return yield* inputFailure("from must use YYYY-MM-DD");
26
+ }
27
+ if (to !== undefined && !/^\d{4}-\d{2}-\d{2}$/.test(to)) {
28
+ return yield* inputFailure("to must use YYYY-MM-DD");
29
+ }
30
+ if (from !== undefined && to !== undefined && from > to) {
31
+ return yield* inputFailure("from must be on or before to");
32
+ }
33
+ if (query !== undefined && (query.length === 0 || query.length > 200)) {
34
+ return yield* inputFailure(query.length === 0
35
+ ? "query must not be empty"
36
+ : "query must be at most 200 characters");
37
+ }
38
+ if (currency !== undefined && !isCurrency(currency)) {
39
+ return yield* inputFailure("currency must be one of USD, CAD, EUR, GBP");
40
+ }
41
+ return { groupId, from, to, query, currency };
42
+ });
43
+ const renderSpendSummary = (summary) => {
44
+ const sections = [formatTable(["FIELD", "VALUE"], [
45
+ ["Currency", summary.currency],
46
+ ["Group", summary.groupId ?? "all groups"],
47
+ ["From", summary.from ?? "—"],
48
+ ["To", summary.to ?? "—"],
49
+ ["Query", summary.query ?? "—"],
50
+ ["Expenses", String(summary.expenseCount)],
51
+ ["Total spent", `${summary.totalSpent} ${summary.currency}`],
52
+ ["You paid", `${summary.yourPaid} ${summary.currency}`],
53
+ ["Your share", `${summary.yourShare} ${summary.currency}`]
54
+ ])];
55
+ if (summary.byPerson.length > 0) {
56
+ sections.push(`By person\n${formatTable(["PERSON", "PAID", "SHARE"], summary.byPerson.map((person) => [
57
+ person.name,
58
+ `${person.paid} ${summary.currency}`,
59
+ `${person.share} ${summary.currency}`
60
+ ]))}`);
61
+ }
62
+ if (summary.byMonth.length > 0) {
63
+ sections.push(`By month\n${formatTable(["MONTH", "TOTAL", "COUNT"], summary.byMonth.map((month) => [
64
+ month.month,
65
+ `${month.total} ${summary.currency}`,
66
+ String(month.count)
67
+ ]))}`);
68
+ }
69
+ if (summary.byDescription.length > 0) {
70
+ sections.push(`By description\n${formatTable(["DESCRIPTION", "TOTAL", "COUNT"], summary.byDescription.map((description) => [
71
+ description.description,
72
+ `${description.total} ${summary.currency}`,
73
+ String(description.count)
74
+ ]))}`);
75
+ }
76
+ if (summary.byGroup.length > 0) {
77
+ sections.push(`By group\n${formatTable(["GROUP", "TOTAL", "COUNT"], summary.byGroup.map((group) => [
78
+ group.groupName ?? group.groupId,
79
+ `${group.total} ${summary.currency}`,
80
+ String(group.count)
81
+ ]))}`);
82
+ }
83
+ return sections.join("\n\n");
84
+ };
85
+ const show = Command.make("show", {
86
+ groupId: groupIdFlag,
87
+ from: fromFlag,
88
+ to: toFlag,
89
+ query: queryFlag,
90
+ currency: currencyFlag,
91
+ json: jsonFlag
92
+ }, Effect.fn(function* (filters) {
93
+ const query = yield* reportFailure(validateSummaryQuery(filters), filters.json);
94
+ const api = yield* ApiClient;
95
+ const response = yield* reportFailure(api.get({
96
+ path: "/spend-summary",
97
+ query,
98
+ schema: GetSpendSummaryResponse
99
+ }), filters.json);
100
+ yield* printSuccess({
101
+ data: response,
102
+ json: filters.json,
103
+ renderHuman: renderSpendSummary
104
+ });
105
+ })).pipe(Command.withDescription("Summarize spending across expenses"));
106
+ export const spendSummaryCommand = Command.make("spend-summary").pipe(Command.withDescription("Inspect spending totals and breakdowns"), Command.withSubcommands([show]));
107
+ //# sourceMappingURL=spend-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spend-summary.js","sourceRoot":"","sources":["../../src/commands/spend-summary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { Command, Prompt } from "effect/unstable/cli";
2
+ import { CliInputError, UpdateError } from "../errors.js";
3
+ import { UpdateService } from "../update/update-service.js";
4
+ export declare const updateCommand: Command.Command<"update", {
5
+ readonly check: boolean;
6
+ readonly yes: boolean;
7
+ readonly json: boolean;
8
+ }, {}, CliInputError | UpdateError | import("effect/Terminal").QuitError, Prompt.Environment | UpdateService>;
9
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAE3D,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAMzD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AA+B3D,eAAO,MAAM,aAAa;;;;6GA2ExB,CAAA"}
@@ -0,0 +1,78 @@
1
+ import { Console, Effect } from "effect";
2
+ import { Command, Flag, Prompt } from "effect/unstable/cli";
3
+ import { CliInputError, UpdateError } from "../errors.js";
4
+ import { printSuccess } from "../output.js";
5
+ import { UpdateService } from "../update/update-service.js";
6
+ import { jsonFlag, reportFailure } from "./shared.js";
7
+ const checkFlag = Flag.Boolean("check").pipe(Flag.withDescription("Check for an update without installing it"), Flag.withDefault(false));
8
+ const yesFlag = Flag.Boolean("yes").pipe(Flag.withDescription("Confirm an available update without prompting"), Flag.withDefault(false));
9
+ const availability = (status) => status.updateAvailable ? "yes" : "no";
10
+ const renderStatus = (status) => [
11
+ `Package: ${status.packageName}`,
12
+ `Current version: ${status.currentVersion}`,
13
+ `Latest version: ${status.latestVersion}`,
14
+ `Update available: ${availability(status)}`,
15
+ `Installation: ${status.installation.method}`,
16
+ `Automatic update: ${status.installation.automaticUpdateSupported ? "supported" : "unsupported"}`,
17
+ `Update command: ${status.installation.updateCommand ?? "—"}`,
18
+ `Guidance: ${status.installation.guidance}`
19
+ ].join("\n");
20
+ const renderResult = (result) => result.updated
21
+ ? `Updated ${result.packageName} from ${result.currentVersion} to ${result.latestVersion}.`
22
+ : `Already up to date.\n${renderStatus(result)}`;
23
+ export const updateCommand = Command.make("update", {
24
+ check: checkFlag,
25
+ yes: yesFlag,
26
+ json: jsonFlag
27
+ }, Effect.fn(function* ({ check, yes, json }) {
28
+ if (!check && !yes && (json || !process.stdin.isTTY)) {
29
+ return yield* reportFailure(Effect.fail(new CliInputError({
30
+ message: "update requires --yes in non-interactive mode"
31
+ })), json);
32
+ }
33
+ const service = yield* UpdateService;
34
+ const status = yield* reportFailure(service.check, json);
35
+ if (check) {
36
+ yield* printSuccess({
37
+ data: status,
38
+ json,
39
+ renderHuman: renderStatus
40
+ });
41
+ return;
42
+ }
43
+ if (!status.updateAvailable) {
44
+ yield* printSuccess({
45
+ data: { ...status, updated: false },
46
+ json,
47
+ renderHuman: renderResult
48
+ });
49
+ return;
50
+ }
51
+ if (!status.installation.automaticUpdateSupported) {
52
+ return yield* reportFailure(Effect.fail(new UpdateError({
53
+ code: "UPDATE_UNSUPPORTED",
54
+ message: status.installation.guidance,
55
+ ...(status.installation.updateCommand === null
56
+ ? {}
57
+ : { command: status.installation.updateCommand })
58
+ })), json);
59
+ }
60
+ if (!yes) {
61
+ yield* Console.log(renderStatus(status));
62
+ const confirmed = yield* Prompt.run(Prompt.Confirm({
63
+ message: `Run ${status.installation.updateCommand}?`,
64
+ initial: false
65
+ }));
66
+ if (!confirmed) {
67
+ yield* Console.log("Update cancelled.");
68
+ return;
69
+ }
70
+ }
71
+ yield* reportFailure(service.install(status, { captureOutput: json }), json);
72
+ yield* printSuccess({
73
+ data: { ...status, updated: true },
74
+ json,
75
+ renderHuman: renderResult
76
+ });
77
+ })).pipe(Command.withDescription("Check for or install the latest AllSquare CLI release"));
78
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { Config, Context, Effect, Layer, Option } from "effect";
2
+ import { CliConfigError } from "./errors.js";
3
+ export declare const DEFAULT_API_URL = "https://allsquare.app/api/v1";
4
+ export declare const parseApiUrl: (input: string) => Effect.Effect<string, CliConfigError>;
5
+ export declare const customConfigDirectory: Config.Config<Option.Option<string>>;
6
+ declare const CliConfig_base: Context.ServiceClass<CliConfig, "@allsquare/cli/CliConfig", {
7
+ readonly apiUrl: Effect.Effect<string, CliConfigError>;
8
+ readonly configDirectory: Effect.Effect<string, Config.ConfigError>;
9
+ }>;
10
+ export declare class CliConfig extends CliConfig_base {
11
+ static readonly layer: Layer.Layer<CliConfig, never, never>;
12
+ }
13
+ export {};
14
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE5C,eAAO,MAAM,eAAe,iCAAiC,CAAA;AAI7D,eAAO,MAAM,WAAW,GACtB,OAAO,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAwBnC,CAAA;AAaJ,eAAO,MAAM,qBAAqB,sCAAyC,CAAA;;qBAwBxD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC;8BAC5B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC;;AAFrE,qBAAa,SAAU,SAAQ,cAGC;IAC9B,MAAM,CAAC,QAAQ,CAAC,KAAK,uCAGpB;CACF"}
package/dist/config.js ADDED
@@ -0,0 +1,52 @@
1
+ import { homedir } from "node:os";
2
+ import process from "node:process";
3
+ import { Config, Context, Effect, Layer, Option } from "effect";
4
+ import { CliConfigError } from "./errors.js";
5
+ export const DEFAULT_API_URL = "https://allsquare.app/api/v1";
6
+ const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]"]);
7
+ export const parseApiUrl = (input) => Effect.try({
8
+ try: () => {
9
+ const url = new URL(input);
10
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
11
+ throw new Error("Only HTTP and HTTPS URLs are supported");
12
+ }
13
+ if (url.protocol === "http:" && !LOOPBACK_HOSTS.has(url.hostname)) {
14
+ throw new Error("HTTP is only allowed for loopback development URLs");
15
+ }
16
+ if (url.username || url.password || url.search || url.hash) {
17
+ throw new Error("Credentials, query parameters, and fragments are not allowed");
18
+ }
19
+ url.pathname = url.pathname.replace(/\/+$/, "") || "/";
20
+ return url.toString().replace(/\/$/, "");
21
+ },
22
+ catch: (cause) => new CliConfigError({
23
+ message: `Invalid ALLSQUARE_API_URL: ${cause instanceof Error ? cause.message : String(cause)}`
24
+ })
25
+ });
26
+ const apiUrl = Config.String("ALLSQUARE_API_URL").pipe(Config.withDefault(DEFAULT_API_URL), Effect.mapError((cause) => new CliConfigError({
27
+ message: `Unable to read ALLSQUARE_API_URL: ${cause.message}`
28
+ })), Effect.flatMap(parseApiUrl));
29
+ const optionalConfig = (name) => Config.String(name).pipe(Config.option);
30
+ export const customConfigDirectory = optionalConfig("ALLSQUARE_CONFIG_DIR");
31
+ const configDirectory = Effect.gen(function* () {
32
+ const explicit = yield* customConfigDirectory;
33
+ if (Option.isSome(explicit))
34
+ return explicit.value;
35
+ if (process.platform === "win32") {
36
+ const appData = yield* optionalConfig("APPDATA");
37
+ return Option.isSome(appData)
38
+ ? `${appData.value}\\AllSquare`
39
+ : `${homedir()}\\AppData\\Roaming\\AllSquare`;
40
+ }
41
+ if (process.platform === "darwin") {
42
+ return `${homedir()}/Library/Application Support/AllSquare`;
43
+ }
44
+ const xdgConfigHome = yield* optionalConfig("XDG_CONFIG_HOME");
45
+ return Option.isSome(xdgConfigHome)
46
+ ? `${xdgConfigHome.value}/allsquare`
47
+ : `${homedir()}/.config/allsquare`;
48
+ });
49
+ export class CliConfig extends Context.Service()("@allsquare/cli/CliConfig") {
50
+ static layer = Layer.succeed(CliConfig, CliConfig.of({ apiUrl, configDirectory }));
51
+ }
52
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,OAAO,MAAM,cAAc,CAAA;AAElC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE5C,MAAM,CAAC,MAAM,eAAe,GAAG,8BAA8B,CAAA;AAE7D,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAA;AAEnE,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,KAAa,EAC0B,EAAE,CACzC,MAAM,CAAC,GAAG,CAAC;IACT,GAAG,EAAE,GAAG,EAAE;QACR,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAA;QAE1B,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAA;QAC3D,CAAC;QAED,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;QACvE,CAAC;QAED,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAA;QACjF,CAAC;QAED,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAA;QACtD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAC1C,CAAC;IACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,cAAc,CAAC;QACjB,OAAO,EAAE,8BAA8B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;KAChG,CAAC;CACL,CAAC,CAAA;AAEJ,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,CACpD,MAAM,CAAC,WAAW,CAAC,eAAe,CAAC,EACnC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CACxB,IAAI,cAAc,CAAC;IACjB,OAAO,EAAE,qCAAqC,KAAK,CAAC,OAAO,EAAE;CAC9D,CAAC,CAAC,EACL,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAC5B,CAAA;AAED,MAAM,cAAc,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;AAEhF,MAAM,CAAC,MAAM,qBAAqB,GAAG,cAAc,CAAC,sBAAsB,CAAC,CAAA;AAE3E,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,qBAAqB,CAAA;IAC7C,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAA;IAElD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAA;QAChD,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;YAC3B,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,aAAa;YAC/B,CAAC,CAAC,GAAG,OAAO,EAAE,+BAA+B,CAAA;IACjD,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,GAAG,OAAO,EAAE,wCAAwC,CAAA;IAC7D,CAAC;IAED,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAA;IAC9D,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;QACjC,CAAC,CAAC,GAAG,aAAa,CAAC,KAAK,YAAY;QACpC,CAAC,CAAC,GAAG,OAAO,EAAE,oBAAoB,CAAA;AACtC,CAAC,CAAC,CAAA;AAEF,MAAM,OAAO,SAAU,SAAQ,OAAO,CAAC,OAAO,EAG1C,CAAC,0BAA0B,CAAC;IAC9B,MAAM,CAAU,KAAK,GAAG,KAAK,CAAC,OAAO,CACnC,SAAS,EACT,SAAS,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAC1C,CAAA"}