Skip to content

Commit

Permalink
chore: add apollo
Browse files Browse the repository at this point in the history
  • Loading branch information
pipinet committed Sep 30, 2024
1 parent 35dac47 commit e947bcb
Show file tree
Hide file tree
Showing 16 changed files with 592 additions and 49 deletions.
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@
"name": "@dorami/monorepo",
"module": "index.ts",
"type": "module",
"version": "0.0.2",
"version": "0.0.0",
"private": true,
"scripts": {
"setup": "rm -rf **/node_modules **/dist ./pnpm-lock.yaml && pnpm install",
"link": "pnpm --filter './packages/*' dev:link",
"release": "pnpm run build && pnpm recursive publish --filter './packages/*' --no-git-checks --report-summary",
"build": "NODE_ENV=production pnpm run build:check && pnpm run build:packages",
"build:check": "pnpm run format:check && pnpm run security:check",
"build:packages": "pnpm run build:lang",
"build:lang": "pnpm --filter lang build",
"build:packages": "pnpm --filter './packages/*' build",
"dev": "pnpm --filter showcase dev",
"hot:dev": "DEV_ENV=hot pnpm --filter showcase dev",
"security:check": "pnpm audit --prod --audit-level high",
Expand Down
1 change: 1 addition & 0 deletions packages/apollo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- TODO
52 changes: 52 additions & 0 deletions packages/apollo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "@dorami/apollo",
"version": "0.0.0",
"main": "./src/index.ts",
"module": "./src/index.ts",
"types": "./src/index.ts",
"publishConfig": {
"main": "./index.mjs",
"module": "./index.mjs",
"types": "./index.d.mts",
"exports": {
".": {
"types": "./index.d.mts",
"import": "./index.mjs"
}
},
"directory": "dist",
"linkDirectory": false,
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"scripts": {
"build": "NODE_ENV=production INPUT_DIR=./ OUTPUT_DIR=dist/ pnpm run build:package",
"build:package": "pnpm run build:prebuild && tsup && pnpm run build:postbuild",
"build:prebuild": "tsx ./scripts/prebuild.ts",
"build:postbuild": "tsx ./scripts/postbuild.ts",
"dev:link": "pnpm link --global && npm link"
},
"dependencies": {
"@apollo/client": "^3.11.8",
"@vue/apollo-composable": "^4.2.1"
},
"devDependencies": {
"tsup": "^8.2.4",
"tsx": "^4.16.2"
},
"author": "Qwlabs",
"homepage": "https://github.com/qwlabs/dorami",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/qwlabs/dorami.git",
"directory": "packages/apollo"
},
"bugs": {
"url": "https://github.com/qwlabs/dorami/issues"
},
"engines": {
"node": ">=20.17.0",
"pnpm": ">=9"
}
}
11 changes: 11 additions & 0 deletions packages/apollo/scripts/postbuild.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as path from 'node:path';
import * as fs from 'fs-extra';
import { clearPackageJson, resolvePath } from '../../../scripts/build-helper';

const { __dirname, __workspace, OUTPUT_DIR } = resolvePath(import.meta.url);

fs.copySync(path.resolve(__dirname, '../package.json'), `${OUTPUT_DIR}/package.json`);
fs.copySync(path.resolve(__dirname, '../README.md'), `${OUTPUT_DIR}/README.md`);
fs.copySync(path.resolve(__workspace, './LICENSE.md'), `${OUTPUT_DIR}/LICENSE.md`);

clearPackageJson(path.resolve(__dirname, `../${OUTPUT_DIR}/package.json`));
5 changes: 5 additions & 0 deletions packages/apollo/scripts/prebuild.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as path from 'node:path';
import { removeBuild, resolvePath, updatePackageJson } from '../../../scripts/build-helper';

removeBuild(import.meta.url);
updatePackageJson(path.resolve(resolvePath(import.meta.url).__dirname, '../package.json'));
94 changes: 94 additions & 0 deletions packages/apollo/src/graphql-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import type { ApolloCache, NormalizedCacheObject, Operation } from '@apollo/client/core';
import type { GraphqlApiClientConfig } from './models';
import { ApolloClient, ApolloLink, createHttpLink, InMemoryCache, split } from '@apollo/client/core';
import { onError } from '@apollo/client/link/error';
import { getMainDefinition } from '@apollo/client/utilities';
import { DEFAULT_OPTIONS } from './models';

const loadHeaders = (config: GraphqlApiClientConfig): Record<string, any> => {
let headers: Record<string, any> = {};
headers['Content-Type'] = 'application/json;charset=UTF-8';
headers['Accept-Language'] = 'zh-CN';
if (config.headerAugmentor) {
headers = config.headerAugmentor(headers);
}
return headers;
};

const createAHttpLink = (config: GraphqlApiClientConfig): ApolloLink => {
const normalHttpLink = createHttpLink({
uri: (params: Operation) => {
return `${config.url}?op=${params.operationName}`;
},
});
const batchHttpLink = createHttpLink({
uri: config.url,
});
return split(() => config.batchEnabled, batchHttpLink, normalHttpLink);
};

const createWSLink = (config: GraphqlApiClientConfig): ApolloLink => {
return ApolloLink.from([]);
};

const createGraphqlLink = (config: GraphqlApiClientConfig): ApolloLink => {
const httpLink = createAHttpLink(config);
const wsLink = createWSLink(config);
return split(
({ query }) => {
const definition = getMainDefinition(query);
return definition.kind === 'OperationDefinition' && definition.operation === 'subscription';
},
wsLink,
httpLink
);
};

const createErrorLink = (config: GraphqlApiClientConfig): ApolloLink => {
return onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors != null && graphQLErrors.length > 0) {
graphQLErrors.forEach((graphQLError) => {
const handler = config.graphQLErrorHandlers.find((handler) => handler.match(graphQLError));
handler?.handle(graphQLError);
});
}
if (networkError) {
const handler = config.networkErrorHandlers.find((handler) => handler.match(networkError));
handler?.handle(networkError);
}
});
};

const createMiddleware = (config: GraphqlApiClientConfig): ApolloLink => {
return new ApolloLink((operation, forward) => {
operation.setContext({
headers: loadHeaders(config),
});
return forward(operation);
});
};

const createLink = (config: GraphqlApiClientConfig): ApolloLink => {
const middleware = createMiddleware(config);
const graphqlLink = createGraphqlLink(config);
const errorLink = createErrorLink(config);
return ApolloLink.from([errorLink, middleware, graphqlLink]);
};

export const createClient = (config: GraphqlApiClientConfig): { client: ApolloClient<any>; cache: ApolloCache<NormalizedCacheObject> } => {
const link = createLink(config);
const cache = new InMemoryCache({
resultCaching: true,
});
const client = new ApolloClient({
link,
cache,
ssrMode: config.ssrMode,
queryDeduplication: true,
defaultOptions: config.defaultOptions ?? DEFAULT_OPTIONS,
devtools: {
enabled: config.connectToDevTools,
}
});
return { client, cache };
};
13 changes: 13 additions & 0 deletions packages/apollo/src/graphql-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export interface RelyEdge<N> {
node: N;
}

export interface RelyConnection<N> {
edges: RelyEdge<N>[];
}

export const extractRelyData = <N, R>(connection: unknown, mapping?: (node: N) => R): R[] => {
return ((connection as RelyConnection<N>)?.edges ?? []).map((edge: RelyEdge<N>) => {
return mapping ? mapping(edge.node) : (edge.node as unknown as R);
});
};
3 changes: 3 additions & 0 deletions packages/apollo/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './graphql-client';
export * from './graphql-helpers';
export * from './models';
53 changes: 53 additions & 0 deletions packages/apollo/src/models.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { FetchResult, Observable } from '@apollo/client';
import type { DefaultOptions } from '@apollo/client/core/ApolloClient';
import type { NetworkError } from '@apollo/client/errors';
import type { GraphQLFormattedError } from 'graphql/error/GraphQLError';

export type RequestHeaderAugmentor = (headers: Record<string, any>) => Record<string, any>;

export interface ErrorMatchHandler {
match: (error: Error) => boolean;

handle: (error: Error) => Observable<FetchResult> | void;
}

export interface NetworkErrorMatchHandler extends ErrorMatchHandler {
match: (error: NetworkError) => boolean;

handle: (error: NetworkError) => Observable<FetchResult> | void;
}

export interface GraphQLErrorMatchHandler extends ErrorMatchHandler {
match: (error: GraphQLFormattedError) => boolean;

handle: (error: GraphQLFormattedError) => Observable<FetchResult> | void;
}

export interface GraphqlApiClientConfig {
ssrMode: boolean;
connectToDevTools: boolean;
url: string;
subscriptionUrl?: string;
batchEnabled: boolean;
headerAugmentor?: RequestHeaderAugmentor;
networkErrorHandlers: NetworkErrorMatchHandler[];
graphQLErrorHandlers: GraphQLErrorMatchHandler[];
defaultOptions?: DefaultOptions;
}

export const DEFAULT_OPTIONS: DefaultOptions = {
query: {
notifyOnNetworkStatusChange: true,
fetchPolicy: 'no-cache',
},
mutate: {
fetchPolicy: 'no-cache',
keepRootFields: true,
},
watchQuery: {
notifyOnNetworkStatusChange: true,
fetchPolicy: 'no-cache',
nextFetchPolicy: 'no-cache',
returnPartialData: true,
},
};
11 changes: 11 additions & 0 deletions packages/apollo/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Node",
"baseUrl": "."
},
"exclude": [
"node_modules",
"dist"
]
}
8 changes: 8 additions & 0 deletions packages/apollo/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { defineConfig } from 'tsup';

export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
dts: true,
splitting: false,
});
7 changes: 4 additions & 3 deletions packages/lang/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"name": "@dorami/lang",
"version": "0.0.2",
"version": "0.0.0",
"main": "./src/index.ts",
"module": "./src/index.ts",
"types": "./src/index.ts",
"publishConfig": {
"main": "./index.mjs",
"module": "./index.mjs",
Expand Down Expand Up @@ -34,14 +35,14 @@
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/qwlabs/dorami.git"
"url": "git+https://github.com/qwlabs/dorami.git",
"directory": "packages/lang"
},
"bugs": {
"url": "https://github.com/qwlabs/dorami/issues"
},
"engines": {
"node": ">=20.17.0",
"bun": ">=1",
"pnpm": ">=9"
}
}
12 changes: 6 additions & 6 deletions packages/lang/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Node",
"baseUrl": ".",
},
"exclude": ["node_modules", "dist"]
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Node",
"baseUrl": ".",
},
"exclude": ["node_modules", "dist"]
}
Loading

0 comments on commit e947bcb

Please sign in to comment.