feature: add mgraphql codegen

This commit is contained in:
2025-04-29 02:22:06 +08:00
parent 0300d7baf6
commit 9fdb778330
16 changed files with 3844 additions and 70 deletions

View File

@@ -0,0 +1,110 @@
/* eslint-disable */
import type {
DocumentTypeDecoration,
ResultOf,
TypedDocumentNode,
} from '@graphql-typed-document-node/core';
import type { FragmentDefinitionNode } from 'graphql';
import type { Incremental } from './graphql';
export type FragmentType<
TDocumentType extends DocumentTypeDecoration<any, any>,
> = TDocumentType extends DocumentTypeDecoration<infer TType, any>
? [TType] extends [{ ' $fragmentName'?: infer TKey }]
? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never
: never
: never;
// return non-nullable if `fragmentType` is non-nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>>
): TType;
// return nullable if `fragmentType` is undefined
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | undefined
): TType | undefined;
// return nullable if `fragmentType` is nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null
): TType | null;
// return nullable if `fragmentType` is nullable or undefined
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| FragmentType<DocumentTypeDecoration<TType, any>>
| null
| undefined
): TType | null | undefined;
// return array of non-nullable if `fragmentType` is array of non-nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: Array<FragmentType<DocumentTypeDecoration<TType, any>>>
): Array<TType>;
// return array of nullable if `fragmentType` is array of nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| Array<FragmentType<DocumentTypeDecoration<TType, any>>>
| null
| undefined
): Array<TType> | null | undefined;
// return readonly array of non-nullable if `fragmentType` is array of non-nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
): ReadonlyArray<TType>;
// return readonly array of nullable if `fragmentType` is array of nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
| null
| undefined
): ReadonlyArray<TType> | null | undefined;
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| FragmentType<DocumentTypeDecoration<TType, any>>
| Array<FragmentType<DocumentTypeDecoration<TType, any>>>
| ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
| null
| undefined
): TType | Array<TType> | ReadonlyArray<TType> | null | undefined {
return fragmentType as any;
}
export function makeFragmentData<
F extends DocumentTypeDecoration<any, any>,
FT extends ResultOf<F>,
>(data: FT, _fragment: F): FragmentType<F> {
return data as FragmentType<F>;
}
export function isFragmentReady<TQuery, TFrag>(
queryNode: DocumentTypeDecoration<TQuery, any>,
fragmentNode: TypedDocumentNode<TFrag>,
data:
| FragmentType<TypedDocumentNode<Incremental<TFrag>, any>>
| null
| undefined
): data is FragmentType<typeof fragmentNode> {
const deferredFields = (
queryNode as {
__meta__?: { deferredFields: Record<string, (keyof TFrag)[]> };
}
).__meta__?.deferredFields;
if (!deferredFields) return true;
const fragDef = fragmentNode.definitions[0] as
| FragmentDefinitionNode
| undefined;
const fragName = fragDef?.name?.value;
const fields = (fragName && deferredFields[fragName]) || [];
return fields.length > 0 && fields.every((field) => data && field in data);
}

View File

@@ -0,0 +1,59 @@
import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
/* eslint-disable */
import * as types from './graphql';
/**
* Map of all GraphQL operations in the project.
*
* This map has several performance disadvantages:
* 1. It is not tree-shakeable, so it will include all operations in the project.
* 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle.
* 3. It does not support dead code elimination, so it will add unused operations.
*
* Therefore it is highly recommended to use the babel or swc plugin for production.
* Learn more about it here: https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#reducing-bundle-size
*/
type Documents = {
'\n mutation CreateSubscription($input: SubscriptionsInsertInput!) {\n subscriptionsCreateOne(data: $input) {\n id\n displayName\n sourceUrl\n enabled\n category\n subscriberId\n }\n }\n': typeof types.CreateSubscriptionDocument;
'\n query GetSubscriptions($page: Int!, $pageSize: Int!) {\n subscriptions(\n pagination: {\n page: {\n page: $page,\n limit: $pageSize\n }\n }\n ) {\n nodes {\n id\n displayName\n category\n enabled\n bangumi {\n nodes {\n id\n displayName\n posterLink\n season\n fansub\n homepage\n }\n }\n }\n }\n }\n': typeof types.GetSubscriptionsDocument;
};
const documents: Documents = {
'\n mutation CreateSubscription($input: SubscriptionsInsertInput!) {\n subscriptionsCreateOne(data: $input) {\n id\n displayName\n sourceUrl\n enabled\n category\n subscriberId\n }\n }\n':
types.CreateSubscriptionDocument,
'\n query GetSubscriptions($page: Int!, $pageSize: Int!) {\n subscriptions(\n pagination: {\n page: {\n page: $page,\n limit: $pageSize\n }\n }\n ) {\n nodes {\n id\n displayName\n category\n enabled\n bangumi {\n nodes {\n id\n displayName\n posterLink\n season\n fansub\n homepage\n }\n }\n }\n }\n }\n':
types.GetSubscriptionsDocument,
};
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*
*
* @example
* ```ts
* const query = gql(`query GetUser($id: ID!) { user(id: $id) { name } }`);
* ```
*
* The query argument is unknown!
* Please regenerate the types.
*/
export function gql(source: string): unknown;
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(
source: '\n mutation CreateSubscription($input: SubscriptionsInsertInput!) {\n subscriptionsCreateOne(data: $input) {\n id\n displayName\n sourceUrl\n enabled\n category\n subscriberId\n }\n }\n'
): (typeof documents)['\n mutation CreateSubscription($input: SubscriptionsInsertInput!) {\n subscriptionsCreateOne(data: $input) {\n id\n displayName\n sourceUrl\n enabled\n category\n subscriberId\n }\n }\n'];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(
source: '\n query GetSubscriptions($page: Int!, $pageSize: Int!) {\n subscriptions(\n pagination: {\n page: {\n page: $page,\n limit: $pageSize\n }\n }\n ) {\n nodes {\n id\n displayName\n category\n enabled\n bangumi {\n nodes {\n id\n displayName\n posterLink\n season\n fansub\n homepage\n }\n }\n }\n }\n }\n'
): (typeof documents)['\n query GetSubscriptions($page: Int!, $pageSize: Int!) {\n subscriptions(\n pagination: {\n page: {\n page: $page,\n limit: $pageSize\n }\n }\n ) {\n nodes {\n id\n displayName\n category\n enabled\n bangumi {\n nodes {\n id\n displayName\n posterLink\n season\n fansub\n homepage\n }\n }\n }\n }\n }\n'];
export function gql(source: string) {
return (documents as any)[source] ?? {};
}
export type DocumentType<TDocumentNode extends DocumentNode<any, any>> =
TDocumentNode extends DocumentNode<infer TType, any> ? TType : never;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
export * from './fragment-masking';
export * from './gql';

View File

@@ -1,3 +1,7 @@
import type { Injector } from '@outposts/injection-js';
import { atomWithObservable } from 'jotai/utils';
import { useInjector } from 'oidc-client-rx/adapters/react';
import { useMemo } from 'react';
import { ThemeService } from './theme.service';
export function provideStyles() {
@@ -8,3 +12,37 @@ export function provideStyles() {
},
];
}
export function themeContextFromInjector(injector: Injector) {
const themeService = injector.get(ThemeService);
const systemColorSchema$ = atomWithObservable(
() => themeService.systemColorSchema$
);
return {
themeService,
systemColorSchema$,
};
}
export function setupThemeContext(injector: Injector) {
const { themeService } = themeContextFromInjector(injector);
themeService.setup();
}
export function useTheme() {
const injector = useInjector();
const { themeService } = useMemo(() => {
return themeContextFromInjector(injector);
}, [injector]);
const colorTheme = useMemo(
() => atomWithObservable(() => themeService.colorSchema$),
[themeService]
);
return {
themeService,
colorTheme,
};
}

View File

@@ -1,7 +1,17 @@
import { DOCUMENT } from '@/infra/platform/injection';
import { LocalStorageService } from '@/infra/storage/web-storage.service';
import { Injectable, inject } from '@outposts/injection-js';
import {
BehaviorSubject,
ReplaySubject,
combineLatest,
distinctUntilChanged,
filter,
fromEvent,
map,
shareReplay,
startWith,
} from 'rxjs';
export type PreferColorSchemaType = 'dark' | 'light' | 'system';
export type PreferColorSchemaClass = 'dark' | 'light';
@@ -9,6 +19,71 @@ export type PreferColorSchemaClass = 'dark' | 'light';
export class ThemeService {
document = inject(DOCUMENT);
localStorage = inject(LocalStorageService);
systemColorSchema$ = new BehaviorSubject(this.systemColorSchema);
storageColorSchema$ = new BehaviorSubject(
this.getColorSchemaType(this.localStorage.getItem('prefers-color-scheme'))
);
colorSchema$ = new BehaviorSubject(
this.getColorSchemaByType(
this.storageColorSchema$.value,
this.systemColorSchema$.value
)
);
setup() {
const mediaQuery = this.document.defaultView?.matchMedia(
'(prefers-color-scheme: dark)'
);
if (mediaQuery) {
fromEvent(mediaQuery, 'change')
.pipe(
map(() => (mediaQuery.matches ? 'dark' : 'light')),
startWith(this.systemColorSchema),
distinctUntilChanged()
)
.subscribe(this.systemColorSchema$);
}
if (this.document.defaultView?.localStorage) {
fromEvent(this.document.defaultView, 'storage')
.pipe(
filter(
(e): e is StorageEvent =>
(e as StorageEvent)?.key === 'prefers-color-scheme'
),
map((event) => this.getColorSchemaType(event.newValue)),
distinctUntilChanged()
)
.subscribe(this.storageColorSchema$);
}
combineLatest({
system: this.systemColorSchema$,
storage: this.storageColorSchema$,
})
.pipe(
map(({ system, storage }) => this.getColorSchemaByType(storage, system))
)
.subscribe(this.colorSchema$);
}
private getColorSchemaType(themeType: string | null): PreferColorSchemaType {
if (themeType === 'dark' || themeType === 'light') {
return themeType as PreferColorSchemaType;
}
return 'system';
}
private getColorSchemaByType(
themeType: PreferColorSchemaType,
systemColorSchema: PreferColorSchemaClass
): PreferColorSchemaClass {
if (themeType === 'dark' || themeType === 'light') {
return themeType;
}
return systemColorSchema;
}
get systemColorSchema(): PreferColorSchemaClass {
return this.document.defaultView?.matchMedia('(prefers-color-scheme: dark)')
@@ -17,24 +92,16 @@ export class ThemeService {
: 'light';
}
private getColorSchemaByType(
themeType: PreferColorSchemaType
): PreferColorSchemaClass {
this.document.documentElement.classList.remove('dark', 'light');
if (themeType === 'dark' || themeType === 'light') {
return themeType;
}
return this.systemColorSchema;
}
get colorSchema() {
const theme = this.localStorage.getItem('prefers-color-scheme');
return this.getColorSchemaByType(theme as PreferColorSchemaType);
return this.colorSchema$.value;
}
set colorSchema(themeType: PreferColorSchemaType) {
this.localStorage.setItem('prefers-color-scheme', themeType);
const themeClass = this.getColorSchemaByType(themeType);
const themeClass = this.getColorSchemaByType(
themeType,
this.systemColorSchema
);
this.document.documentElement.classList.remove('dark', 'light');
this.document.documentElement.classList.add(themeClass);
}