@sbc-connect/nuxt-pay 0.4.0 → 0.5.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 +13 -0
- package/app/services/helpers/get-cached-or-fetch.ts +43 -0
- package/app/services/helpers/index.ts +1 -0
- package/app/services/index.ts +1 -0
- package/app/services/pay/index.ts +4 -0
- package/app/services/pay/mutate.ts +1 -0
- package/app/services/pay/query-keys.ts +24 -0
- package/app/services/pay/query.ts +64 -0
- package/app/services/pay/service.ts +30 -0
- package/app/stores/connect-fee.ts +6 -6
- package/nuxt.config.ts +1 -1
- package/package.json +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @sbc-connect/nuxt-pay
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#172](https://github.com/bcgov/connect-nuxt/pull/172) [`c9e5d05`](https://github.com/bcgov/connect-nuxt/commit/c9e5d0519aff914196c38242f3a827473261af38) Thanks [@deetz99](https://github.com/deetz99)! - Implement useConnectPayQuery query defintions, useConnectPayService cache abstraction and update usage in connect-fee store.
|
|
8
|
+
|
|
9
|
+
## 0.4.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`d91712d`](https://github.com/bcgov/connect-nuxt/commit/d91712db74c2e0c6b39f6fd38955fd60e82ce691)]:
|
|
14
|
+
- @sbc-connect/nuxt-auth@0.12.0
|
|
15
|
+
|
|
3
16
|
## 0.4.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { DefineQueryOptions } from '@pinia/colada'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolves a query from the cache or fetches it from the network if necessary.
|
|
5
|
+
* * This utility ensures a cache entry exists and handles data fetching
|
|
6
|
+
* based on the current cache state and the `force` flag.
|
|
7
|
+
*
|
|
8
|
+
* @template TData - The expected shape of the data returned by the query.
|
|
9
|
+
* @template TError - The error type if the query fails. Defaults to `Error`.
|
|
10
|
+
* * @param options - The query definition object
|
|
11
|
+
* containing the key, query function, and cache settings (e.g., staleTime).
|
|
12
|
+
* @param [force=false] - When true, bypasses the cache and triggers
|
|
13
|
+
* a network call (cache.fetch). When false, returns cached data if fresh,
|
|
14
|
+
* or background refreshes if stale or in error state (cache.refresh).
|
|
15
|
+
* * @returns A promise that resolves to the query data.
|
|
16
|
+
* @throws throws the underlying network error if the fetch or refresh fails.
|
|
17
|
+
* * @example
|
|
18
|
+
* // uses cache if fresh
|
|
19
|
+
* const business = await getCachedOrFetch(businessOptions('BC123'));
|
|
20
|
+
* * // Forced fetch: ignores cache and hits API
|
|
21
|
+
* const freshData = await getCachedOrFetch(businessOptions('BC123'), true);
|
|
22
|
+
*/
|
|
23
|
+
export async function getCachedOrFetch<TData>(
|
|
24
|
+
options: DefineQueryOptions<TData>,
|
|
25
|
+
force = false
|
|
26
|
+
): Promise<TData> {
|
|
27
|
+
const cache = useQueryCache()
|
|
28
|
+
// NB: Required to prevent calls within 1ms causing a promise to return before the cached response is complete.
|
|
29
|
+
// i.e. without below:
|
|
30
|
+
// -> Call 1 for BC1234567 data
|
|
31
|
+
// -> Call 2 for BC1234567 data within 1ms
|
|
32
|
+
// -> Call 1 is cancelled
|
|
33
|
+
// -> Promise returns with undefined response from Call 1 instead of awaiting Call 2
|
|
34
|
+
await new Promise(resolve => setTimeout(resolve, 1))
|
|
35
|
+
// Ensures a query entry is present in the cache.
|
|
36
|
+
// will create one if it doesn't exist
|
|
37
|
+
const entry = cache.ensure(options)
|
|
38
|
+
const result = force
|
|
39
|
+
? await cache.fetch(entry)
|
|
40
|
+
: await cache.refresh(entry)
|
|
41
|
+
|
|
42
|
+
return result.data!
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './get-cached-or-fetch'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './pay'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// TBD
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// https://pinia-colada.esm.dev/guide/query-keys.html
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* IMPORTANT: Query Key Hierarchy
|
|
5
|
+
* * Our cache follows a strict hierarchy: ['connect', 'pay', accountId, ...rest].
|
|
6
|
+
* * 1. Account ID: The 'base' (accountId) MUST remain as the first dynamic segment.
|
|
7
|
+
* This allows us to invalidate an entire "folder" by targeting the parent key.
|
|
8
|
+
* * 2. ORDER: When updating keys, ensure the order of existing segments is preserved.
|
|
9
|
+
* Changing the order may break existing invalidation logic across the app.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export const useConnectPayQueryKeys = () => {
|
|
13
|
+
const { currentAccount } = storeToRefs(useConnectAccountStore())
|
|
14
|
+
|
|
15
|
+
const base = () => ['connect', 'pay', currentAccount.value?.id] as const
|
|
16
|
+
|
|
17
|
+
const keys = {
|
|
18
|
+
fee: (entityType: string, code: string, params: { priority?: boolean, futureEffective?: boolean } = {}) =>
|
|
19
|
+
[...base(), 'fee', entityType, code, params] as const,
|
|
20
|
+
payAccount: (accountId: string | number) => [...base(), 'pay-account', accountId] as const
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return { keys }
|
|
24
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// IMPORTANT: Query definitions are for GET requests only - for all other methods define a mutation in the ./mutate file
|
|
2
|
+
// https://pinia-colada.esm.dev/guide/queries.html
|
|
3
|
+
import { useQuery } from '@pinia/colada'
|
|
4
|
+
import type { UseQueryOptions, DefineQueryOptions } from '@pinia/colada'
|
|
5
|
+
|
|
6
|
+
type QueryOptions<T> = Omit<UseQueryOptions<T>, 'key' | 'query'> & {
|
|
7
|
+
query?: UseQueryOptions<T>['query']
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type DefineOptions<TData, TError = Error> = Omit<DefineQueryOptions<TData, TError>, 'key' | 'query'> & {
|
|
11
|
+
query?: DefineQueryOptions<TData, TError>['query']
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const DEFAULT_STALE_TIME = 60000
|
|
15
|
+
|
|
16
|
+
export const useConnectPayQuery = () => {
|
|
17
|
+
const { $payApi } = useNuxtApp()
|
|
18
|
+
const { keys } = useConnectPayQueryKeys()
|
|
19
|
+
|
|
20
|
+
function feeOptions(
|
|
21
|
+
entityType: string,
|
|
22
|
+
code: string,
|
|
23
|
+
params?: { priority?: boolean, futureEffective?: boolean },
|
|
24
|
+
options?: DefineOptions<ConnectFeeItem>) {
|
|
25
|
+
return defineQueryOptions({
|
|
26
|
+
query: () => $payApi<ConnectFeeItem>(`/fees/${entityType}/${code}`, { params }),
|
|
27
|
+
staleTime: DEFAULT_STALE_TIME,
|
|
28
|
+
...options,
|
|
29
|
+
key: keys.fee(entityType, code, params)
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function fee(
|
|
34
|
+
entityType: string,
|
|
35
|
+
code: string,
|
|
36
|
+
params?: { priority?: boolean, futureEffective?: boolean },
|
|
37
|
+
options?: QueryOptions<ConnectFeeItem>) {
|
|
38
|
+
return useQuery(() => feeOptions(entityType, code, params, options as DefineOptions<ConnectFeeItem>))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function payAccountOptions(
|
|
42
|
+
accountId: string | number,
|
|
43
|
+
options?: DefineOptions<ConnectPayAccount>) {
|
|
44
|
+
return defineQueryOptions({
|
|
45
|
+
query: () => $payApi<ConnectPayAccount>(`/accounts/${accountId}`),
|
|
46
|
+
staleTime: DEFAULT_STALE_TIME,
|
|
47
|
+
...options,
|
|
48
|
+
key: keys.payAccount(accountId)
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function payAccount(
|
|
53
|
+
accountId: string | number,
|
|
54
|
+
options?: QueryOptions<ConnectPayAccount>) {
|
|
55
|
+
return useQuery(() => payAccountOptions(accountId, options as DefineOptions<ConnectPayAccount>))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
feeOptions,
|
|
60
|
+
fee,
|
|
61
|
+
payAccountOptions,
|
|
62
|
+
payAccount
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getCachedOrFetch } from '../helpers'
|
|
2
|
+
|
|
3
|
+
export const useConnectPayService = () => {
|
|
4
|
+
const query = useConnectPayQuery()
|
|
5
|
+
|
|
6
|
+
/* GET Requests */
|
|
7
|
+
|
|
8
|
+
async function getFee(
|
|
9
|
+
entityType: string,
|
|
10
|
+
code: string,
|
|
11
|
+
params?: { priority?: boolean, futureEffective?: boolean },
|
|
12
|
+
force = false
|
|
13
|
+
): Promise<ConnectFeeItem> {
|
|
14
|
+
const options = query.feeOptions(entityType, code, params)
|
|
15
|
+
return await getCachedOrFetch(options, force)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function getPayAccount(
|
|
19
|
+
accountId: string | number,
|
|
20
|
+
force = false
|
|
21
|
+
): Promise<ConnectPayAccount> {
|
|
22
|
+
const options = query.payAccountOptions(accountId)
|
|
23
|
+
return await getCachedOrFetch(options, force)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
getFee,
|
|
28
|
+
getPayAccount
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const useConnectFeeStore = defineStore('connect-pay-fee-store', () => {
|
|
2
|
-
const
|
|
2
|
+
const service = useConnectPayService()
|
|
3
3
|
const { t } = useNuxtApp().$i18n
|
|
4
4
|
const { baseModal } = useConnectModal()
|
|
5
5
|
|
|
@@ -139,7 +139,7 @@ export const useConnectFeeStore = defineStore('connect-pay-fee-store', () => {
|
|
|
139
139
|
priority: true,
|
|
140
140
|
futureEffective: true
|
|
141
141
|
}
|
|
142
|
-
return await
|
|
142
|
+
return await service.getFee(entityType, code, params)
|
|
143
143
|
} catch (error) {
|
|
144
144
|
console.error('Error fetching Fee: ', error)
|
|
145
145
|
}
|
|
@@ -226,13 +226,13 @@ export const useConnectFeeStore = defineStore('connect-pay-fee-store', () => {
|
|
|
226
226
|
const accountId = useConnectAccountStore().currentAccount.id
|
|
227
227
|
try {
|
|
228
228
|
// get payment account
|
|
229
|
-
|
|
230
|
-
userPaymentAccount.value
|
|
229
|
+
userPaymentAccount.value = await service.getPayAccount(accountId)
|
|
230
|
+
const { cfsAccount } = userPaymentAccount.value
|
|
231
231
|
|
|
232
232
|
// add options to allowedPaymentMethods
|
|
233
233
|
let defaultMethod = userPaymentAccount.value.paymentMethod
|
|
234
234
|
if (defaultMethod !== undefined) {
|
|
235
|
-
const accountNum =
|
|
235
|
+
const accountNum = cfsAccount?.bankAccountNumber ?? ''
|
|
236
236
|
allowedPaymentMethods.value.push({
|
|
237
237
|
label: t(`connect.payMethod.label.${defaultMethod}`, { account: accountNum }),
|
|
238
238
|
value: defaultMethod
|
|
@@ -245,7 +245,7 @@ export const useConnectFeeStore = defineStore('connect-pay-fee-store', () => {
|
|
|
245
245
|
value: ConnectPayMethod.DIRECT_PAY
|
|
246
246
|
})
|
|
247
247
|
// if pad in confirmation period then set default payment to CC
|
|
248
|
-
if (PAD_PENDING_STATES.includes(
|
|
248
|
+
if (PAD_PENDING_STATES.includes(cfsAccount?.status)) {
|
|
249
249
|
defaultMethod = ConnectPayMethod.DIRECT_PAY
|
|
250
250
|
}
|
|
251
251
|
}
|
package/nuxt.config.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sbc-connect/nuxt-pay",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"repository": "github:bcgov/connect-nuxt",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
7
|
"main": "./nuxt.config.ts",
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
"nuxt": "4.4.6",
|
|
12
12
|
"typescript": "6.0.3",
|
|
13
13
|
"vue-tsc": "3.3.1",
|
|
14
|
-
"@sbc-connect/
|
|
14
|
+
"@sbc-connect/playwright-config": "0.2.0",
|
|
15
15
|
"@sbc-connect/vitest-config": "0.2.0",
|
|
16
|
-
"@sbc-connect/
|
|
16
|
+
"@sbc-connect/eslint-config": "0.0.8"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@sbc-connect/nuxt-auth": "0.
|
|
19
|
+
"@sbc-connect/nuxt-auth": "0.12.0"
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"preinstall": "npx only-allow pnpm",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"lint:fix": "eslint --fix .",
|
|
30
30
|
"test": "pnpm run test:unit; pnpm run test:e2e",
|
|
31
31
|
"test:unit": "vitest run",
|
|
32
|
+
"test:unit:watch": "vitest",
|
|
32
33
|
"test:unit:cov": "vitest --dir tests/unit --coverage",
|
|
33
34
|
"test:e2e": "npx playwright test",
|
|
34
35
|
"test:e2e:ui": "npx playwright test --ui",
|