@vrplatform/graphql 1.0.0-staging.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/build/main/client/headers.d.ts +3 -0
- package/build/main/client/headers.js +42 -0
- package/build/main/client/index.d.ts +13 -0
- package/build/main/client/index.js +103 -0
- package/build/main/client/subscription.d.ts +3 -0
- package/build/main/client/subscription.js +29 -0
- package/build/main/common/account.d.ts +2 -0
- package/build/main/common/account.js +7 -0
- package/build/main/common/address.d.ts +9 -0
- package/build/main/common/address.js +2 -0
- package/build/main/common/bank-record.d.ts +2 -0
- package/build/main/common/bank-record.js +7 -0
- package/build/main/common/index.d.ts +5 -0
- package/build/main/common/index.js +21 -0
- package/build/main/common/listings.d.ts +4 -0
- package/build/main/common/listings.js +99 -0
- package/build/main/common/tenant.d.ts +19 -0
- package/build/main/common/tenant.js +85 -0
- package/build/main/constants.d.ts +2 -0
- package/build/main/constants.js +5 -0
- package/build/main/error.d.ts +2 -0
- package/build/main/error.js +6 -0
- package/build/main/gqty/index.d.ts +8 -0
- package/build/main/gqty/index.js +65 -0
- package/build/main/gqty/schema.generated.d.ts +109775 -0
- package/build/main/gqty/schema.generated.js +43373 -0
- package/build/main/index.d.ts +5 -0
- package/build/main/index.js +25 -0
- package/build/main/tsconfig.main.tsbuildinfo +1 -0
- package/build/main/types.d.ts +15 -0
- package/build/main/types.js +2 -0
- package/build/main/wrap.d.ts +12 -0
- package/build/main/wrap.js +47 -0
- package/build/module/client/headers.d.ts +3 -0
- package/build/module/client/headers.js +39 -0
- package/build/module/client/index.d.ts +13 -0
- package/build/module/client/index.js +98 -0
- package/build/module/client/subscription.d.ts +3 -0
- package/build/module/client/subscription.js +26 -0
- package/build/module/common/account.d.ts +2 -0
- package/build/module/common/account.js +4 -0
- package/build/module/common/address.d.ts +9 -0
- package/build/module/common/address.js +1 -0
- package/build/module/common/bank-record.d.ts +2 -0
- package/build/module/common/bank-record.js +4 -0
- package/build/module/common/index.d.ts +5 -0
- package/build/module/common/index.js +5 -0
- package/build/module/common/listings.d.ts +4 -0
- package/build/module/common/listings.js +93 -0
- package/build/module/common/tenant.d.ts +19 -0
- package/build/module/common/tenant.js +77 -0
- package/build/module/constants.d.ts +2 -0
- package/build/module/constants.js +2 -0
- package/build/module/error.d.ts +2 -0
- package/build/module/error.js +2 -0
- package/build/module/gqty/index.d.ts +8 -0
- package/build/module/gqty/index.js +42 -0
- package/build/module/gqty/schema.generated.d.ts +109775 -0
- package/build/module/gqty/schema.generated.js +43370 -0
- package/build/module/index.d.ts +5 -0
- package/build/module/index.js +5 -0
- package/build/module/tsconfig.esm.tsbuildinfo +1 -0
- package/build/module/types.d.ts +15 -0
- package/build/module/types.js +1 -0
- package/build/module/wrap.d.ts +12 -0
- package/build/module/wrap.js +44 -0
- package/package.json +57 -0
- package/src/client/headers.ts +51 -0
- package/src/client/index.ts +152 -0
- package/src/client/subscription.ts +34 -0
- package/src/common/account.ts +6 -0
- package/src/common/address.ts +9 -0
- package/src/common/bank-record.ts +6 -0
- package/src/common/index.ts +5 -0
- package/src/common/listings.ts +106 -0
- package/src/common/tenant.ts +101 -0
- package/src/constants.ts +2 -0
- package/src/error.ts +1 -0
- package/src/gqty/index.ts +63 -0
- package/src/gqty/schema.generated.d.ts +109775 -0
- package/src/gqty/schema.generated.js +43458 -0
- package/src/index.ts +10 -0
- package/src/types.ts +14 -0
- package/src/wrap.ts +67 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { GQtyClient, GQtyError, ResolveOptions, SubscriptionsClient, } from 'gqty';
|
|
2
|
+
export { type HasuraClient, useHasuraClient } from './client';
|
|
3
|
+
export * from './common';
|
|
4
|
+
export * from './gqty';
|
|
5
|
+
export { type ResolveOptionsWithSession, wrapGraphQLClient } from './wrap';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../../src/constants.ts","../../src/error.ts","../../src/index.ts","../../src/types.ts","../../src/wrap.ts","../../src/client/headers.ts","../../src/client/index.ts","../../src/client/subscription.ts","../../src/common/account.ts","../../src/common/address.ts","../../src/common/bank-record.ts","../../src/common/index.ts","../../src/common/listings.ts","../../src/common/tenant.ts","../../src/gqty/index.ts","../../src/gqty/schema.generated.d.ts","../../src/gqty/schema.generated.js"],"version":"5.9.2"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type Headers = {
|
|
2
|
+
[s: string]: string;
|
|
3
|
+
};
|
|
4
|
+
export type AllowedHeaders = {
|
|
5
|
+
[s: string]: string;
|
|
6
|
+
} | (() => Headers) | (() => Promise<Headers>);
|
|
7
|
+
export type GqlAuthParam = {
|
|
8
|
+
accessToken?: string;
|
|
9
|
+
secret?: string;
|
|
10
|
+
headers?: AllowedHeaders;
|
|
11
|
+
subscriptions?: boolean;
|
|
12
|
+
uri?: string;
|
|
13
|
+
auditUserId?: string;
|
|
14
|
+
credentials?: RequestCredentials;
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GQtyClient, ResolveOptions, SubscriptionsClient } from 'gqty';
|
|
2
|
+
import type { GeneratedSchema } from './gqty';
|
|
3
|
+
export type ResolveOptionsWithSession<T> = ResolveOptions<T>;
|
|
4
|
+
type Client = GQtyClient<GeneratedSchema>;
|
|
5
|
+
export declare function wrapGraphQLClient(getClient: () => Client, subscriptionsClient?: SubscriptionsClient): {
|
|
6
|
+
readonly client: Client;
|
|
7
|
+
subscriptionsClient: SubscriptionsClient;
|
|
8
|
+
mutate<T = unknown>(resolved: (sub: Client["mutation"]) => T, options?: ResolveOptionsWithSession<T>): Promise<T>;
|
|
9
|
+
query<T = unknown>(resolved: (sub: Client["query"]) => T, options?: ResolveOptionsWithSession<T>): Promise<T>;
|
|
10
|
+
subscribe<T = unknown>(resolved: (sub: Client["subscription"]) => T, onData: (data: T, unsubscribeFn: () => Promise<void>) => void, onError?: (err: Error, unsubscribeFn: () => Promise<void>) => void): () => Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function wrapGraphQLClient(getClient, subscriptionsClient) {
|
|
2
|
+
return {
|
|
3
|
+
get client() {
|
|
4
|
+
return getClient();
|
|
5
|
+
},
|
|
6
|
+
subscriptionsClient,
|
|
7
|
+
async mutate(resolved, options) {
|
|
8
|
+
if (!options)
|
|
9
|
+
options = {};
|
|
10
|
+
if (options.noCache === undefined)
|
|
11
|
+
options.noCache = true;
|
|
12
|
+
const client = getClient();
|
|
13
|
+
const result = await client.resolved(() => resolved(client.mutation), options);
|
|
14
|
+
return result;
|
|
15
|
+
},
|
|
16
|
+
async query(resolved, options) {
|
|
17
|
+
const client = getClient();
|
|
18
|
+
const result = await client.resolved(() => resolved(client.query), options);
|
|
19
|
+
return result;
|
|
20
|
+
},
|
|
21
|
+
subscribe(resolved, onData, onError) {
|
|
22
|
+
if (!subscriptionsClient)
|
|
23
|
+
throw new Error('Subscriptions not enabled');
|
|
24
|
+
let unsub;
|
|
25
|
+
const stop = async () => {
|
|
26
|
+
if (!unsub)
|
|
27
|
+
return;
|
|
28
|
+
await unsub().catch(() => undefined);
|
|
29
|
+
};
|
|
30
|
+
const client = getClient();
|
|
31
|
+
client.resolved(() => resolved(client.subscription), {
|
|
32
|
+
onSubscription(event) {
|
|
33
|
+
if (event.unsubscribe)
|
|
34
|
+
unsub = event.unsubscribe;
|
|
35
|
+
if (event.type === 'data')
|
|
36
|
+
onData(event.data, stop);
|
|
37
|
+
else if (event.type === 'with-errors' && onError)
|
|
38
|
+
onError(event.error, stop);
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
return stop;
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vrplatform/graphql",
|
|
3
|
+
"publishConfig": {
|
|
4
|
+
"access": "public"
|
|
5
|
+
},
|
|
6
|
+
"files": [
|
|
7
|
+
"build/main",
|
|
8
|
+
"build/module",
|
|
9
|
+
"src",
|
|
10
|
+
"!**/*.spec.*",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"version": "1.0.0-staging.0",
|
|
14
|
+
"description": "Finalytic graphql",
|
|
15
|
+
"main": "build/main/index.js",
|
|
16
|
+
"module": "build/module/index.js",
|
|
17
|
+
"typings": "build/module/index.d.ts",
|
|
18
|
+
"repository": "https://github.com/vrplatform/graphql",
|
|
19
|
+
"license": "UNLICENSED",
|
|
20
|
+
"keywords": [],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@finalytic/utils": "^4.9.73",
|
|
23
|
+
"@gqty/subscriptions": "^2.0.1-alpha-00594c5.0",
|
|
24
|
+
"gqty": "2.3.0",
|
|
25
|
+
"graphql": "^16.11.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@gqty/cli": "^3.3.0-alpha-d8cdbf6.0"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"check": "bun run typecheck && bun run lint",
|
|
32
|
+
"test": "bun test",
|
|
33
|
+
"lint": "biome check .",
|
|
34
|
+
"pub": "bun pub:pre && pnpm version patch --no-commit-hooks --no-git-tag-version && pnpm publish --no-git-checks",
|
|
35
|
+
"pub-staging": "bun pub:pre && pnpm publish --no-git-checks --tag staging",
|
|
36
|
+
"pub:pre": "bun check && npm run generate && npm run build",
|
|
37
|
+
"typecheck": "tsc --noEmit",
|
|
38
|
+
"build": "run-p build:* && run-p buildcp:*",
|
|
39
|
+
"build:main": "tsc -b tsconfig.main.json",
|
|
40
|
+
"build:module": "tsc -b tsconfig.esm.json",
|
|
41
|
+
"buildcp:copy1": "cp ./src/gqty/schema.generated.d.ts ./build/module/gqty/schema.generated.d.ts",
|
|
42
|
+
"buildcp:copy2": "cp ./src/gqty/schema.generated.d.ts ./build/main/gqty/schema.generated.d.ts",
|
|
43
|
+
"generate": "gqty generate && sleep 1 && npm run post-generate && rm src/gqty/index.js",
|
|
44
|
+
"post-generate": "run-s post-generate:*",
|
|
45
|
+
"post-generate:1": "sed -i '' 's/export type Maybe<T> = T | null/export type Maybe<T> = T/g' ./src/gqty/schema.generated.d.ts",
|
|
46
|
+
"post-generate:2": "sed -i '' 's/InputMaybe<T> = Maybe<T>/InputMaybe<T> = T | null/g' ./src/gqty/schema.generated.d.ts",
|
|
47
|
+
"post-generate:3": "sed -i '' 's/ScalarsEnums extends MakeNullable<Scalars>/ScalarsEnums extends Scalars/g' ./src/gqty/schema.generated.d.ts",
|
|
48
|
+
"post-generate:4": "sed -i '' 's/timestamptz: any;/timestamptz: string;/g' ./src/gqty/schema.generated.d.ts",
|
|
49
|
+
"post-generate:5": "sed -i '' 's/timestamp: any;/timestamp: string;/g' ./src/gqty/schema.generated.d.ts",
|
|
50
|
+
"post-generate:6": "sed -i '' 's/bigint: any;/bigint: number;/g' ./src/gqty/schema.generated.d.ts",
|
|
51
|
+
"post-generate:7": "sed -i '' 's/Float: any;/Float: number;/g' ./src/gqty/schema.generated.d.ts",
|
|
52
|
+
"post-generate:8": "sed -i '' 's/float8: any;/float8: number;/g' ./src/gqty/schema.generated.d.ts",
|
|
53
|
+
"post-generate:9": "sed -i '' 's/numeric: any;/numeric: number;/g' ./src/gqty/schema.generated.d.ts",
|
|
54
|
+
"post-generate:10": "sed -i '' 's/uuid: any;/uuid: string;/g' ./src/gqty/schema.generated.d.ts",
|
|
55
|
+
"post-generate:11": "sed -i '' 's/date: any;/date: string;/g' ./src/gqty/schema.generated.d.ts"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { GqlAuthParam, Headers } from '../types';
|
|
2
|
+
|
|
3
|
+
// Create headers factory function
|
|
4
|
+
export function createHeadersFactory(
|
|
5
|
+
args?: Pick<
|
|
6
|
+
GqlAuthParam,
|
|
7
|
+
'headers' | 'secret' | 'accessToken' | 'auditUserId'
|
|
8
|
+
>
|
|
9
|
+
) {
|
|
10
|
+
return async (base?: Headers): Promise<Headers> => {
|
|
11
|
+
const result: Record<string, string> = {};
|
|
12
|
+
|
|
13
|
+
// Add static or function headers
|
|
14
|
+
if (args?.headers) {
|
|
15
|
+
if (typeof args.headers === 'function') {
|
|
16
|
+
const functionResult = await args.headers();
|
|
17
|
+
for (const key in functionResult) {
|
|
18
|
+
result[key] = functionResult[key];
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
for (const key in args.headers) {
|
|
22
|
+
result[key] = args.headers[key];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Add base headers
|
|
28
|
+
if (base) {
|
|
29
|
+
for (const key in base) {
|
|
30
|
+
result[key] = base[key];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Add auth headers
|
|
35
|
+
if (args?.secret) {
|
|
36
|
+
result['x-hasura-admin-secret'] = args.secret;
|
|
37
|
+
} else if (args?.accessToken) {
|
|
38
|
+
result.authorization = args.accessToken.startsWith('Bearer ')
|
|
39
|
+
? args.accessToken
|
|
40
|
+
: `Bearer ${args.accessToken}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (args?.auditUserId) {
|
|
44
|
+
result['x-hasura-audit-user-id'] = args.auditUserId;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type HeadersFactory = ReturnType<typeof createHeadersFactory>;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defaultAssertRetryableResponse,
|
|
3
|
+
formatResponse,
|
|
4
|
+
type RetryableFetchParams,
|
|
5
|
+
useRetryableFetch,
|
|
6
|
+
} from '@finalytic/utils';
|
|
7
|
+
import { createClient, type GQtyClient } from 'gqty';
|
|
8
|
+
import { hasuraGraphqlUri, hasuraQueryTypeHeader } from '../constants';
|
|
9
|
+
import {
|
|
10
|
+
type GeneratedSchema,
|
|
11
|
+
generatedSchema,
|
|
12
|
+
type SchemaObjectTypes,
|
|
13
|
+
type SchemaObjectTypesNames,
|
|
14
|
+
scalarsEnumsHash,
|
|
15
|
+
} from '../gqty';
|
|
16
|
+
import type { GqlAuthParam } from '../types';
|
|
17
|
+
import { wrapGraphQLClient } from '../wrap';
|
|
18
|
+
import { createHeadersFactory } from './headers';
|
|
19
|
+
import { createHasuraSubscriptionsClient } from './subscription';
|
|
20
|
+
|
|
21
|
+
export type HasuraClient = ReturnType<typeof useHasuraClient>;
|
|
22
|
+
|
|
23
|
+
const retryablesErrors = [
|
|
24
|
+
'deadlock detected',
|
|
25
|
+
'fetch failed',
|
|
26
|
+
'Unexpected token',
|
|
27
|
+
'operation exceeded the time limit',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
type HasuraError = {
|
|
31
|
+
errors: {
|
|
32
|
+
extensions: {
|
|
33
|
+
internal: {
|
|
34
|
+
error: {
|
|
35
|
+
message: string;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
message: string;
|
|
40
|
+
}[];
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
function isRetryableResponse(json: HasuraError) {
|
|
44
|
+
if (!json || typeof json !== 'object') return null;
|
|
45
|
+
|
|
46
|
+
const message = JSON.stringify(json.errors || {});
|
|
47
|
+
|
|
48
|
+
if (!message) return null;
|
|
49
|
+
return retryablesErrors.find((e) => message?.includes(e));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const defaultAssertHasuraRetryableResponse: RetryableFetchParams['assertResponse'] =
|
|
53
|
+
async (arg) => {
|
|
54
|
+
const defaultResponse = await defaultAssertRetryableResponse(arg);
|
|
55
|
+
if (defaultResponse && 'retryable' in defaultResponse)
|
|
56
|
+
return defaultResponse;
|
|
57
|
+
|
|
58
|
+
const json = await formatResponse(arg.response).catch(() => null);
|
|
59
|
+
arg.response.json = () => json;
|
|
60
|
+
const retryableResponse = isRetryableResponse(json);
|
|
61
|
+
if (retryableResponse) {
|
|
62
|
+
return {
|
|
63
|
+
retryable: true,
|
|
64
|
+
errorMessage: retryableResponse,
|
|
65
|
+
errorDetails: json,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export function useHasuraClient({
|
|
71
|
+
uri = hasuraGraphqlUri,
|
|
72
|
+
secret,
|
|
73
|
+
auditUserId,
|
|
74
|
+
accessToken,
|
|
75
|
+
subscriptions,
|
|
76
|
+
headers,
|
|
77
|
+
credentials,
|
|
78
|
+
...retryableFetchArgs
|
|
79
|
+
}: GqlAuthParam & RetryableFetchParams = {}) {
|
|
80
|
+
const getHeaders = createHeadersFactory({
|
|
81
|
+
accessToken,
|
|
82
|
+
auditUserId,
|
|
83
|
+
headers,
|
|
84
|
+
secret,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Create the subscriptions client if needed
|
|
88
|
+
const subscriptionsClient = createHasuraSubscriptionsClient(
|
|
89
|
+
uri,
|
|
90
|
+
getHeaders,
|
|
91
|
+
subscriptions !== false
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const fetchFn: typeof globalThis.fetch =
|
|
95
|
+
retryableFetchArgs.fetch || (fetch as any);
|
|
96
|
+
const attempts =
|
|
97
|
+
retryableFetchArgs.attempts === undefined ? 3 : retryableFetchArgs.attempts;
|
|
98
|
+
const retryableFetch =
|
|
99
|
+
attempts > 1
|
|
100
|
+
? useRetryableFetch({
|
|
101
|
+
assertResponse: defaultAssertHasuraRetryableResponse,
|
|
102
|
+
...retryableFetchArgs,
|
|
103
|
+
attempts,
|
|
104
|
+
})
|
|
105
|
+
: undefined;
|
|
106
|
+
|
|
107
|
+
// Create the GQty client
|
|
108
|
+
const client: () => GQtyClient<GeneratedSchema> = () =>
|
|
109
|
+
createClient<GeneratedSchema, SchemaObjectTypesNames, SchemaObjectTypes>({
|
|
110
|
+
schema: generatedSchema,
|
|
111
|
+
scalarsEnumsHash,
|
|
112
|
+
async queryFetcher(query, variables, fetchOptions) {
|
|
113
|
+
const getRequest = async () => {
|
|
114
|
+
const headers = await getHeaders({
|
|
115
|
+
'Content-Type': 'application/json',
|
|
116
|
+
});
|
|
117
|
+
if (fetchOptions?.headers) {
|
|
118
|
+
for (const key in fetchOptions.headers) {
|
|
119
|
+
headers[key] = fetchOptions.headers[key];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const isMutation = query.includes('mutation');
|
|
123
|
+
headers[hasuraQueryTypeHeader] = isMutation ? 'mutation' : 'query';
|
|
124
|
+
return new Request(uri, {
|
|
125
|
+
method: 'POST',
|
|
126
|
+
credentials,
|
|
127
|
+
headers,
|
|
128
|
+
body: JSON.stringify({
|
|
129
|
+
query,
|
|
130
|
+
variables,
|
|
131
|
+
}),
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
const response = retryableFetch
|
|
135
|
+
? await retryableFetch(getRequest)
|
|
136
|
+
: await fetchFn(await getRequest());
|
|
137
|
+
const json = await response.json();
|
|
138
|
+
return json;
|
|
139
|
+
},
|
|
140
|
+
subscriptionsClient,
|
|
141
|
+
normalization: false,
|
|
142
|
+
defaults: {
|
|
143
|
+
resolved: {
|
|
144
|
+
noCache: true,
|
|
145
|
+
retry: false, // We're handling retries ourselves in queryFetcher
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
retry: { maxRetries: 0 },
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
return wrapGraphQLClient(client, subscriptionsClient);
|
|
152
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createSubscriptionsClient } from '@gqty/subscriptions';
|
|
2
|
+
import type { SubscriptionsClient } from 'gqty';
|
|
3
|
+
import { hasuraQueryTypeHeader } from '../constants';
|
|
4
|
+
import type { Headers } from '../types';
|
|
5
|
+
|
|
6
|
+
// Create subscriptions client
|
|
7
|
+
export function createHasuraSubscriptionsClient(
|
|
8
|
+
uri: string,
|
|
9
|
+
getHeaders: (base?: Headers) => Promise<Headers>,
|
|
10
|
+
enabled = true
|
|
11
|
+
): SubscriptionsClient | undefined {
|
|
12
|
+
// Ensure we strictly check for false, not falsy values
|
|
13
|
+
if (enabled === false) {
|
|
14
|
+
// We must return undefined here, not a client when disabled
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const wsUrl = new URL(uri);
|
|
20
|
+
wsUrl.protocol = wsUrl.protocol
|
|
21
|
+
.replace('https', 'wss')
|
|
22
|
+
.replace('http', 'ws');
|
|
23
|
+
|
|
24
|
+
return createSubscriptionsClient({
|
|
25
|
+
wsEndpoint: wsUrl.href,
|
|
26
|
+
connectionInitPayload: async () => ({
|
|
27
|
+
headers: await getHeaders({ [hasuraQueryTypeHeader]: 'subscription' }),
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error('Failed to create subscriptions client:', error);
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { hasValue, utc } from '@finalytic/utils';
|
|
2
|
+
import type { listing_bool_exp } from '../gqty';
|
|
3
|
+
|
|
4
|
+
export function whereListingIsActive(): listing_bool_exp {
|
|
5
|
+
return {
|
|
6
|
+
_or: [
|
|
7
|
+
{
|
|
8
|
+
// LEGACY teams
|
|
9
|
+
tenant: {
|
|
10
|
+
isGeneralLedger: { _eq: false },
|
|
11
|
+
},
|
|
12
|
+
calculatedStatus: { _eq: 'active' },
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
// GL teams
|
|
16
|
+
tenant: {
|
|
17
|
+
isGeneralLedger: { _eq: true },
|
|
18
|
+
},
|
|
19
|
+
...whereGlListingIsActive(undefined, utc().yyyymmdd()),
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function whereGlListingIsActive(
|
|
26
|
+
where?: listing_bool_exp,
|
|
27
|
+
date: string = utc().yyyymmdd()
|
|
28
|
+
): listing_bool_exp {
|
|
29
|
+
const statusWhere = {
|
|
30
|
+
_or: [
|
|
31
|
+
{
|
|
32
|
+
_not: {
|
|
33
|
+
ownershipPeriods: {},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
ownershipPeriods: {
|
|
38
|
+
setListingInactive: { _eq: false },
|
|
39
|
+
_or: [
|
|
40
|
+
{
|
|
41
|
+
startAt: {
|
|
42
|
+
_lt: date,
|
|
43
|
+
},
|
|
44
|
+
endAt: {
|
|
45
|
+
_gte: date,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
startAt: {
|
|
50
|
+
_lt: date,
|
|
51
|
+
},
|
|
52
|
+
endAt: {
|
|
53
|
+
_is_null: true,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
} satisfies listing_bool_exp;
|
|
61
|
+
|
|
62
|
+
if (where) return { _and: [statusWhere, where] };
|
|
63
|
+
|
|
64
|
+
return statusWhere;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const whereGlListingIsInactive = (
|
|
68
|
+
where?: listing_bool_exp,
|
|
69
|
+
date: string = utc().yyyymmdd(),
|
|
70
|
+
includeUpcoming = false
|
|
71
|
+
): listing_bool_exp => {
|
|
72
|
+
const statusWhere = {
|
|
73
|
+
ownershipPeriods: {
|
|
74
|
+
setListingInactive: { _eq: true },
|
|
75
|
+
_or: [
|
|
76
|
+
includeUpcoming
|
|
77
|
+
? {
|
|
78
|
+
startAt: {
|
|
79
|
+
_gte: date,
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
: undefined,
|
|
83
|
+
{
|
|
84
|
+
startAt: {
|
|
85
|
+
_lt: date,
|
|
86
|
+
},
|
|
87
|
+
endAt: {
|
|
88
|
+
_gte: date,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
startAt: {
|
|
93
|
+
_lt: date,
|
|
94
|
+
},
|
|
95
|
+
endAt: {
|
|
96
|
+
_is_null: true,
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
].filter(hasValue),
|
|
100
|
+
},
|
|
101
|
+
} satisfies listing_bool_exp;
|
|
102
|
+
|
|
103
|
+
if (where) return { _and: [statusWhere, where] };
|
|
104
|
+
|
|
105
|
+
return statusWhere;
|
|
106
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { utc } from '@finalytic/utils';
|
|
2
|
+
import { HasuraError } from '../error';
|
|
3
|
+
import type { tenant_bool_exp } from '../gqty';
|
|
4
|
+
|
|
5
|
+
// Tenants
|
|
6
|
+
export const VRP_TENANT_ID = '7bfec41f-aa3f-4602-95d2-f7996e4f0e59';
|
|
7
|
+
export const DEMO_TEST_PARTNER_TENANT_ID =
|
|
8
|
+
'0b6a7bd6-56cc-46b5-b2ab-1bd7d1e994fa';
|
|
9
|
+
export const XIMPLIFI_TENANT_ID = 'd6ab2bbe-e0fc-48d9-89a3-c3c05f4e79b5';
|
|
10
|
+
|
|
11
|
+
export function whereTenantActive(where?: tenant_bool_exp) {
|
|
12
|
+
const statusWhere: tenant_bool_exp = {
|
|
13
|
+
calculatedStatus: { _eq: 'active' },
|
|
14
|
+
_or: [
|
|
15
|
+
{
|
|
16
|
+
calculatedBillingPartner: { calculatedStatus: { _eq: 'active' } },
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
calculatedBillingPartnerId: { _is_null: true },
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
if (where) return { _and: [statusWhere, where] };
|
|
25
|
+
|
|
26
|
+
return statusWhere;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function assertTenantActive(tenant: {
|
|
30
|
+
calculatedStatus?: string;
|
|
31
|
+
calculatedBillingPartner?: { calculatedStatus?: string };
|
|
32
|
+
}) {
|
|
33
|
+
if (
|
|
34
|
+
tenant.calculatedStatus !== 'active' ||
|
|
35
|
+
tenant.calculatedBillingPartner?.calculatedStatus !== 'active'
|
|
36
|
+
)
|
|
37
|
+
throw new HasuraError('Tenant or billing partner are not active');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function mapTenantStatus(tenant: {
|
|
41
|
+
calculatedStatus?: string;
|
|
42
|
+
calculatedBillingPartner?: { calculatedStatus?: string };
|
|
43
|
+
}): 'active' | 'inactive' {
|
|
44
|
+
const status = tenant.calculatedStatus === 'active';
|
|
45
|
+
const partnerStatus = tenant.calculatedBillingPartner?.calculatedStatus;
|
|
46
|
+
|
|
47
|
+
return status && partnerStatus === 'active' ? 'active' : 'inactive';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function whereTenantNotTestTeam(where?: tenant_bool_exp) {
|
|
51
|
+
const statusWhere: tenant_bool_exp = {
|
|
52
|
+
id: { _nin: [VRP_TENANT_ID, DEMO_TEST_PARTNER_TENANT_ID] },
|
|
53
|
+
partnerId: {
|
|
54
|
+
_neq: DEMO_TEST_PARTNER_TENANT_ID,
|
|
55
|
+
},
|
|
56
|
+
_or: [
|
|
57
|
+
{ billingPartnerId: { _neq: DEMO_TEST_PARTNER_TENANT_ID } },
|
|
58
|
+
{ billingPartnerId: { _is_null: true } },
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
if (where) return { _and: [statusWhere, where] };
|
|
63
|
+
|
|
64
|
+
return statusWhere;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function whereTenantShouldBePaid(
|
|
68
|
+
where?: tenant_bool_exp,
|
|
69
|
+
includePartnerTeams = false
|
|
70
|
+
) {
|
|
71
|
+
let statusWhere: tenant_bool_exp = {
|
|
72
|
+
isOnboarding: {
|
|
73
|
+
_eq: false, // has left onboarding
|
|
74
|
+
},
|
|
75
|
+
// tenant has no trial or trial ended
|
|
76
|
+
_or: [
|
|
77
|
+
{
|
|
78
|
+
trialUntil: {
|
|
79
|
+
_lt: utc().yyyymmdd(),
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
trialUntil: {
|
|
84
|
+
_is_null: true,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
if (!includePartnerTeams)
|
|
91
|
+
statusWhere = {
|
|
92
|
+
...statusWhere,
|
|
93
|
+
calculatedIsBillable: {
|
|
94
|
+
_eq: true, // no partner teams
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
if (where) statusWhere = { _and: [statusWhere, where] };
|
|
99
|
+
|
|
100
|
+
return whereTenantActive(statusWhere);
|
|
101
|
+
}
|
package/src/constants.ts
ADDED
package/src/error.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class HasuraError extends Error {}
|