snapshot of https://github.com/toeverything/AFFiNE.git (canary, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Build & Test / Analyze (javascript, affine) (push) Failing after 4s
Build & Test / Analyze (typescript, affine) (push) Failing after 3s
Build & Test / Rust test filter (push) Failing after 4s
Build & Test / Check yarn binary (push) Failing after 3s
Build & Test / E2E BlockSuite Test (3) (push) Failing after 3s
Build & Test / Analyze (javascript, blocksuite) (push) Failing after 3s
Build & Test / Analyze (typescript, blocksuite) (push) Failing after 3s
Build & Test / Mobile native build filter (push) Failing after 3s
Build & Test / E2E BlockSuite Test (1) (push) Failing after 4s
Build & Test / E2E BlockSuite Test (2) (push) Failing after 4s
Build & Test / E2E Mobile Test (1) (push) Failing after 3s
Build & Test / Unit Test (1) (push) Has been skipped
Build & Test / Unit Test (2) (push) Has been skipped
Build & Test / Unit Test (3) (push) Has been skipped
Build & Test / Unit Test (4) (push) Has been skipped
Build & Test / Unit Test (5) (push) Has been skipped
Build & Test / Native Unit Test (push) Has been skipped
Build & Test / E2E BlockSuite Test (4) (push) Failing after 3s
Build & Test / E2E BlockSuite Test (5) (push) Failing after 3s
Build & Test / E2E BlockSuite Cross Browser Test (push) Failing after 3s
Build & Test / E2E Mobile Test (2) (push) Failing after 3s
Build & Test / Build AFFiNE native (x86_64-unknown-linux-gnu) (push) Failing after 3s
Build & Test / Build Server native (push) Failing after 3s
Build & Test / Check Git Status (push) Has been skipped
Build & Test / Server Test (0, 4) (push) Has been skipped
Build & Test / Server Test (1, 4) (push) Has been skipped
Build & Test / Server Test (2, 4) (push) Has been skipped
Build & Test / Server Test (3, 4) (push) Has been skipped
Build & Test / Server Test with Elasticsearch (push) Has been skipped
Build & Test / Build @affine/electron renderer (push) Failing after 3s
Build & Test / Copilot test filter (push) Failing after 4s
Build & Test / Lint Rust (push) Has been skipped
Build & Test / Server Test with Embedded Search (push) Has been skipped
Build & Test / Server Test with Manticore Search (push) Has been skipped
Build & Test / Server E2E Test (push) Has been skipped
Build & Test / Cloud Desktop E2E Test (push) Has been skipped
Build & Test / Cloud E2E Test 1/2 (push) Has been skipped
Build & Test / Cloud E2E Test 2/2 (push) Has been skipped
Build & Test / Build Android app (push) Has been skipped
Build & Test / Test Android app (push) Has been skipped
Build & Test / Run native tests (push) Has been skipped
Build & Test / Server Copilot Api Test (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (1, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (2, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (3, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (4, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (5, 5) (push) Has been skipped
Release / Canary Gate (push) Has been skipped
Build & Test / Build AFFiNE native (aarch64-apple-darwin) (push) Has been cancelled
Build & Test / Lint (push) Has been cancelled
Build & Test / Typecheck (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-apple-darwin) (push) Has been cancelled
Build & Test / Desktop Test (ubuntu-latest, linux, x64, x86_64-unknown-linux-gnu, true) (push) Has been cancelled
Build & Test / Desktop Test (windows-latest, windows, x64, x86_64-pc-windows-msvc, true) (push) Has been cancelled
Build & Test / E2E Test (1) (push) Has been cancelled
Build & Test / E2E Test (2) (push) Has been cancelled
Build & Test / E2E Test (3) (push) Has been cancelled
Build & Test / E2E Test (4) (push) Has been cancelled
Build & Test / E2E Test (5) (push) Has been cancelled
Build & Test / Build AFFiNE native (aarch64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, arm64, aarch64-apple-darwin, true) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, x64, x86_64-apple-darwin, false) (push) Has been cancelled
Build & Test / 3, 2, 1 Launch (push) Has been cancelled
Build & Test / Build iOS app (push) Has been cancelled
Copilot Test Automatically / Setup Test (push) Failing after 1s
Release / Prepare (push) Failing after 2s
Release / Release Cloud (push) Has been skipped
Release / Release Desktop (push) Has been skipped
Release / Release Docker Image (push) Has been skipped
Release / Release Mobile (push) Has been skipped

This commit is contained in:
upstream-mirror
2026-09-16 04:01:20 +05:00
commit 702cc698a7
9990 changed files with 1073618 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
# `GraphQL` client
Auto generated `GraphQL` client for affine.pro

View File

@@ -0,0 +1,34 @@
hooks:
afterOneFileWrite:
- oxfmt --write
config:
strict: true
maybeValue: T | null
declarationKind: interface
avoidOptionals:
field: true
inputValue: false
object: false
defaultValue: false
preResolveTypes: true
namingConvention:
enumValues: keep
scalars:
DateTime: string
Date: string
Decimal: number
UUID: string
ID: string
JSON: Record<string, string>
Upload: File
SafeInt: number
overwrite: true
schema: ../../backend/server/src/schema.gql
documents: ./src/**/*.gql
generates:
./src/schema.ts:
plugins:
- typescript
- typescript-operations
- ./export-gql-plugin.cjs:
output: ./src/graphql/index.ts

View File

@@ -0,0 +1,305 @@
const fs = require('node:fs');
const path = require('node:path');
const { Kind, print, visit, TypeInfo, visitWithTypeInfo } = require('graphql');
const { upperFirst, lowerFirst } = require('lodash');
/**
* return exported name used in runtime.
*
* @param {import('graphql').ExecutableDefinitionNode} def
* @returns {string}
*/
function getExportedName(def) {
const name = lowerFirst(def.name?.value);
const suffix =
def.kind === Kind.OPERATION_DEFINITION
? upperFirst(def.operation)
: 'Fragment';
return name.endsWith(suffix) ? name : name + suffix;
}
/**
* Check if a field is deprecated in the schema
*
* @param {import('graphql').GraphQLSchema} schema
* @param {string} typeName
* @param {string} fieldName
* @returns {boolean}
*/
function fieldDeprecation(schema, typeName, fieldName) {
const type = schema.getType(typeName);
if (!type || !type.getFields) {
return false;
}
const fields = type.getFields();
const field = fields[fieldName];
return field?.deprecationReason
? {
name: fieldName,
reason: field.deprecationReason,
}
: null;
}
/**
* Check if a query uses deprecated fields
*
* @param {import('graphql').GraphQLSchema} schema
* @param {import('graphql').DocumentNode} document
* @returns {boolean}
*/
function parseDeprecations(schema, document) {
const deprecations = [];
const typeInfo = new TypeInfo(schema);
visit(
document,
visitWithTypeInfo(typeInfo, {
Field: {
enter(node) {
const parentType = typeInfo.getParentType();
if (parentType && node.name) {
const fieldName = node.name.value;
let deprecation;
if (
parentType.name &&
(deprecation = fieldDeprecation(
schema,
parentType.name,
fieldName
))
) {
deprecations.push(deprecation);
}
}
},
},
})
);
return deprecations.map(
({ name, reason }) => `'${name}' is deprecated: ${reason}`
);
}
/**
* @type {import('@graphql-codegen/plugin-helpers').CodegenPlugin}
*/
module.exports = {
plugin: (schema, documents, { output }) => {
const defs = new Map();
const queries = [];
const mutations = [];
const nameLocationMap = new Map();
const locationSourceMap = new Map(
documents
.filter(source => !!source.location)
.map(source => [source.location, source])
);
function addDef(exportedName, location) {
if (nameLocationMap.has(exportedName)) {
throw new Error(
`name ${exportedName} export from ${location} are duplicated.`
);
}
nameLocationMap.set(exportedName, location);
}
function parseImports(location) {
if (!location) {
return '';
}
// parse '#import' lines
const importedDefinitions = [];
fs.readFileSync(location, 'utf-8')
.split(/\r\n|\r|\n/)
.forEach(line => {
if (line[0] === '#') {
const [importKeyword, importPath] = line.split(' ').filter(Boolean);
if (importKeyword === '#import') {
const realImportPath = path.posix.join(
location,
'..',
importPath.replace(/["']/g, '')
);
const imports =
locationSourceMap.get(realImportPath)?.document.definitions;
if (imports) {
importedDefinitions.push(...imports);
}
}
}
});
return importedDefinitions
.map(def => `\${${getExportedName(def)}}`)
.join('\n');
}
for (const [location, source] of locationSourceMap) {
if (!source || !source.document || !source.rawSDL) {
return;
}
visit(source.document, {
[Kind.OPERATION_DEFINITION]: {
enter: node => {
if (!node.name) {
throw new Error(
`Anonymous operation definition found in ${location}.`
);
}
const exportedName = getExportedName(node);
addDef(exportedName, location);
// parse 'file' fields
const containsFile = node.variableDefinitions.some(def => {
const varType =
def.type.kind === 'NamedType'
? def.type.name.value
: def?.type?.type?.name?.value;
const checkContainFile = type => {
if (schema.getType(type)?.name === 'Upload') return true;
const typeDef = schema.getType(type);
const fields = typeDef.getFields?.();
if (!fields || typeof fields !== 'object') return false;
for (let field of Object.values(fields)) {
let type = field.type;
while (type.ofType) {
type = type.ofType;
}
if (type.name === 'Upload') {
return true;
}
}
return false;
};
return varType ? checkContainFile(varType) : false;
});
// Check if the query uses deprecated fields
const deprecations = parseDeprecations(schema, source.document);
const imports = parseImports(location);
defs.set(exportedName, {
type: node.operation,
name: exportedName,
operationName: node.name.value,
containsFile,
deprecations,
query: `${print(node)}${imports ? `\n${imports}` : ''}`,
});
if (node.operation === 'query') {
queries.push(exportedName);
} else if (node.operation === 'mutation') {
mutations.push(exportedName);
}
},
},
[Kind.FRAGMENT_DEFINITION]: {
enter: node => {
const exportedName = getExportedName(node);
addDef(exportedName, location);
const imports = parseImports(location);
defs.set(exportedName, {
type: 'fragment',
name: exportedName,
content: `${print(node)}${imports || ''}`,
});
},
},
});
}
const preludes = [
'/* do not manipulate this file manually. */',
`export interface GraphQLQuery {
id: string;
op: string;
query: string;
file?: boolean;
deprecations?: string[];
}`,
];
const operations = [];
defs.forEach(def => {
if (def.type === 'fragment') {
preludes.push(`export const ${def.name} = \`${def.content}\`;`);
} else {
let item = `export const ${def.name} = {
id: '${def.name}' as const,
op: '${def.operationName}',
query: \`${def.query}\`,
`;
if (def.containsFile) {
item += ' file: true,\n';
}
if (def.deprecations.length) {
item += ` deprecations: ${JSON.stringify(def.deprecations)},\n`;
}
item += '};\n';
operations.push(item);
}
});
fs.writeFileSync(
output,
preludes.join('\n') + '\n' + operations.join('\n')
);
const queriesUnion = queries
.map(query => {
const queryName = upperFirst(query);
return `{
name: '${query}',
variables: ${queryName}Variables,
response: ${queryName}
}
`;
})
.join('|');
const mutationsUnion = mutations
.map(query => {
const queryName = upperFirst(query);
return `{
name: '${query}',
variables: ${queryName}Variables,
response: ${queryName}
}
`;
})
.join('|');
const queryTypes = queriesUnion
? `export type Queries = ${queriesUnion}`
: '';
const mutationsTypes = mutationsUnion
? `export type Mutations = ${mutationsUnion}`
: '';
return `
${queryTypes}
${mutationsTypes}
`;
},
validate: (_schema, _documents, { output }) => {
if (!output) {
throw new Error('Export plugin must be used with a output file given');
}
},
};

View File

@@ -0,0 +1,32 @@
{
"name": "@affine/graphql",
"version": "0.27.5",
"description": "Autogenerated GraphQL client for affine.pro",
"license": "MIT",
"type": "module",
"private": true,
"main": "./src/index.ts",
"module": "./src/index.ts",
"exports": {
".": "./src/index.ts"
},
"sideEffects": false,
"devDependencies": {
"@graphql-codegen/cli": "^6.2.1",
"@graphql-codegen/typescript": "^5.0.9",
"@graphql-codegen/typescript-operations": "^5.0.9",
"@types/lodash-es": "^4.17.12",
"oxfmt": "0.63.0",
"vitest": "^4.1.8"
},
"scripts": {
"build": "gql-gen --errors-only"
},
"dependencies": {
"@affine/debug": "workspace:*",
"@affine/error": "workspace:*",
"graphql": "^16.9.0",
"lodash": "^4.18.1",
"lodash-es": "^4.17.23"
}
}

View File

@@ -0,0 +1,107 @@
import type { Mock } from 'vitest';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { gqlFetcherFactory } from '../fetcher';
import type { GraphQLQuery } from '../graphql';
const query: GraphQLQuery = {
id: 'query',
query: 'query { field }',
op: 'query',
};
let fetch: Mock;
let gql: ReturnType<typeof gqlFetcherFactory>;
describe('GraphQL fetcher', () => {
beforeEach(() => {
fetch = vi.fn(() =>
Promise.resolve(
new Response(JSON.stringify({ data: { field: 1 } }), {
headers: {
'content-type': 'application/json',
},
})
)
);
gql = gqlFetcherFactory('https://example.com/graphql', fetch);
});
afterEach(() => {
fetch.mockReset();
});
it('should send POST request to given endpoint', async () => {
await gql(
// @ts-expect-error variables is actually optional
{ query }
);
expect(fetch).toBeCalledTimes(1);
expect(fetch.mock.lastCall?.[0]).toBe('https://example.com/graphql');
const ctx = fetch.mock.lastCall?.[1] as RequestInit;
expect(ctx.method).toBe('POST');
});
it('should send with correct graphql JSON body', async () => {
await gql({
query,
// @ts-expect-error forgive the fake variables
variables: { a: 1, b: '2', c: { d: false } },
});
expect(fetch.mock.lastCall?.[1]).toEqual(
expect.objectContaining({
body: '{"query":"query { field }","variables":{"a":1,"b":"2","c":{"d":false}},"operationName":"query"}',
headers: expect.objectContaining({
'content-type': 'application/json',
'x-operation-name': 'query',
}),
method: 'POST',
})
);
});
it('should correctly ignore nil variables', async () => {
await gql({
query,
// @ts-expect-error forgive the fake variables
variables: { a: false, b: null, c: undefined },
});
expect(fetch.mock.lastCall?.[1].body).toMatchInlineSnapshot(
`"{"query":"query { field }","variables":{"a":false,"b":null},"operationName":"query"}"`
);
await gql({
query,
// @ts-expect-error forgive the fake variables
variables: { a: false, b: null, c: undefined },
keepNilVariables: false,
});
expect(fetch.mock.lastCall?.[1].body).toMatchInlineSnapshot(
`"{"query":"query { field }","variables":{"a":false},"operationName":"query"}"`
);
});
it('should correct handle graphql error', async () => {
fetch.mockResolvedValue(
new Response(
JSON.stringify({
data: null,
errors: [{ message: 'error', path: ['field'] }],
}),
{
headers: {
'content-type': 'application/json',
},
status: 400,
}
)
);
await expect(
gql({ query, variables: void 0 })
).rejects.toMatchInlineSnapshot(`[GraphQLError: error]`);
});
});

View File

@@ -0,0 +1,242 @@
import { DebugLogger } from '@affine/debug';
import { GraphQLError } from '@affine/error';
import type { ExecutionResult } from 'graphql';
import { isNil, isObject, merge } from 'lodash-es';
import type { GraphQLQuery } from './graphql';
import type { Mutations, Queries } from './schema';
export type NotArray<T> = T extends Array<unknown> ? never : T;
export type FetchInit = RequestInit & { timeout?: number };
export type _QueryVariables<Q extends GraphQLQuery> =
Q['id'] extends Queries['name']
? Extract<Queries, { name: Q['id'] }>['variables']
: Q['id'] extends Mutations['name']
? Extract<Mutations, { name: Q['id'] }>['variables']
: undefined;
export type QueryVariables<Q extends GraphQLQuery> =
_QueryVariables<Q> extends never | Record<string, never>
? never
: _QueryVariables<Q>;
export type QueryResponse<Q extends GraphQLQuery> = Extract<
Queries | Mutations,
{ name: Q['id'] }
>['response'];
type NullableKeys<T> = {
[K in keyof T]: null extends T[K] ? K : never;
}[keyof T];
type NonNullableKeys<T> = {
[K in keyof T]: null extends T[K] ? never : K;
}[keyof T];
export type RecursiveMaybeFields<T> = T extends
| number
| boolean
| string
| null
| undefined
? T
: {
[K in NullableKeys<T>]?: RecursiveMaybeFields<T[K]>;
} & {
[K in NonNullableKeys<T>]: RecursiveMaybeFields<T[K]>;
};
type AllowedRequestContext = Omit<RequestInit, 'method' | 'body'>;
export interface RequestBody {
operationName?: string;
variables: any;
query: string;
form?: FormData;
}
type QueryVariablesOption<Q extends GraphQLQuery> =
QueryVariables<Q> extends never
? {
variables?: undefined;
}
: { variables: RecursiveMaybeFields<QueryVariables<Q>> };
export type RequestOptions<Q extends GraphQLQuery> = QueryVariablesOption<Q> & {
/**
* parameter passed to `fetch` function
*/
context?: AllowedRequestContext;
/**
* Whether keep null or undefined value in variables.
*
* if `false` given, `{ a: 0, b: undefined, c: null }` will be converted to `{ a: 0 }`
*
* @default true
*/
keepNilVariables?: boolean;
/**
* Request timeout in milliseconds
* @default 15000
*/
timeout?: number;
/**
* Abort signal
*/
signal?: AbortSignal;
};
export type QueryOptions<Q extends GraphQLQuery> = RequestOptions<Q> & {
query: Q;
};
export type MutationOptions<M extends GraphQLQuery> = RequestOptions<M> & {
mutation: M;
};
function filterEmptyValue(vars: any) {
const newVars: Record<string, any> = {};
Object.entries(vars).forEach(([key, value]) => {
if (isNil(value)) {
return;
}
if (isObject(value) && !(value instanceof File)) {
newVars[key] = filterEmptyValue(value);
return;
}
newVars[key] = value;
});
return newVars;
}
export function transformToForm(body: RequestBody) {
const form = new FormData();
const gqlBody: {
name?: string;
query: string;
variables: any;
map: any;
} = {
query: body.query,
variables: body.variables,
map: {},
};
if (body.operationName) {
gqlBody.name = body.operationName;
}
const map: Record<string, string[]> = {};
const files: File[] = [];
if (body.variables) {
let i = 0;
const buildMap = (key: string, value: any) => {
if (value instanceof File) {
map['' + i] = [key];
files[i] = value;
i++;
} else if (Array.isArray(value)) {
value.forEach((v, index) => {
buildMap(`${key}.${index}`, v);
});
} else if (isObject(value)) {
Object.entries(value).forEach(([k, v]) => {
buildMap(`${key}.${k}`, v);
});
}
};
buildMap('variables', body.variables);
}
form.set('operations', JSON.stringify(gqlBody));
form.set('map', JSON.stringify(map));
for (const [i, file] of files.entries()) {
form.set(`${i}`, file);
}
return form;
}
function formatRequestBody<Q extends GraphQLQuery>({
query,
variables,
keepNilVariables,
}: QueryOptions<Q>): RequestBody | FormData {
const body: RequestBody = {
query: query.query,
variables:
(keepNilVariables ?? true) ? variables : filterEmptyValue(variables),
};
if (query.op) {
body.operationName = query.op;
}
if (query.file) {
return transformToForm(body);
}
return body;
}
export const gqlFetcherFactory = (
endpoint: string,
fetcher: (input: string, init?: FetchInit) => Promise<Response> = fetch
) => {
const logger = new DebugLogger('GraphQL');
const gqlFetch = async <Query extends GraphQLQuery>(
options: QueryOptions<Query>
): Promise<QueryResponse<Query>> => {
if (
BUILD_CONFIG.appBuildType === 'canary' &&
options.query.deprecations?.length
) {
options.query.deprecations.forEach(deprecation => {
logger.warn(deprecation);
});
}
const body = formatRequestBody(options);
const isFormData = body instanceof FormData;
const headers: Record<string, string> = {
'x-operation-name': options.query.op,
};
if (!isFormData) {
headers['content-type'] = 'application/json';
}
const ret = fetcher(
endpoint,
merge(options.context, {
method: 'POST',
headers,
body: isFormData ? body : JSON.stringify(body),
timeout: options.timeout,
signal: options.signal,
})
).then(async res => {
if (res.headers.get('content-type')?.startsWith('application/json')) {
const result = (await res.json()) as ExecutionResult;
if (res.status >= 400 || result.errors) {
if (result.errors && result.errors.length > 0) {
// throw the first error is enough
const firstError = result.errors[0];
throw new GraphQLError(firstError.message, firstError);
} else {
throw new GraphQLError('Empty GraphQL error body');
}
} else if (result.data) {
// we have to cast here because the type of result.data is a union type
return result.data as any;
}
}
throw new GraphQLError(
'GraphQL query responds unexpected result, query ' + options.query.op
);
});
return ret;
};
return gqlFetch;
};

View File

@@ -0,0 +1,39 @@
query adminAllSharedLinks(
$pagination: PaginationInput!
$filter: AdminAllSharedLinksFilterInput
) {
adminAllSharedLinks(pagination: $pagination, filter: $filter) {
totalCount
analyticsWindow {
from
to
timezone
bucket
requestedSize
effectiveSize
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
cursor
node {
workspaceId
docId
title
publishedAt
docUpdatedAt
workspaceOwnerId
lastUpdaterId
shareUrl
views
uniqueViews
guestViews
lastAccessedAt
}
}
}
}

View File

@@ -0,0 +1,64 @@
query adminDashboard($input: AdminDashboardInput) {
adminDashboard(input: $input) {
syncActiveUsers
syncActiveUsersTimeline {
minute
activeUsers
}
syncWindow {
from
to
timezone
bucket
requestedSize
effectiveSize
}
copilotConversations
copilotWindow {
from
to
timezone
bucket
requestedSize
effectiveSize
}
workspaceStorageBytes
blobStorageBytes
workspaceStorageHistory {
date
value
}
blobStorageHistory {
date
value
}
storageWindow {
from
to
timezone
bucket
requestedSize
effectiveSize
}
topSharedLinks {
workspaceId
docId
title
shareUrl
publishedAt
views
uniqueViews
guestViews
lastAccessedAt
}
topSharedLinksWindow {
from
to
timezone
bucket
requestedSize
effectiveSize
}
generatedAt
}
}

View File

@@ -0,0 +1,50 @@
query adminMailDeliveries($input: AdminMailDeliveriesInput) {
adminMailDeliveries(input: $input) {
window {
from
to
timezone
bucket
requestedSize
effectiveSize
}
summary {
total
sent
failed
skipped
canceled
queued
sending
retryWait
successRate
}
byStatus {
key
label
total
points {
bucket
count
}
}
byType {
key
label
total
points {
bucket
count
}
}
byOutcome {
key
label
total
points {
bucket
count
}
}
}
}

View File

@@ -0,0 +1,23 @@
#import '../fragments/password-limits.gql'
#import '../fragments/credentials-requirement.gql'
query adminServerConfig {
serverConfig {
version
baseUrl
name
features
type
initialized
credentialsRequirement {
...CredentialsRequirements
}
availableUpgrade {
changelog
version
publishedAt
url
}
availableUserFeatures
}
}

View File

@@ -0,0 +1,25 @@
mutation adminUpdateWorkspace($input: AdminUpdateWorkspaceInput!) {
adminUpdateWorkspace(input: $input) {
id
public
createdAt
name
avatarKey
enableAi
enableSharing
enableUrlPreview
enableDocEmbedding
owner {
id
name
email
avatarUrl
}
memberCount
publicPageCount
snapshotCount
snapshotSize
blobCount
blobSize
}
}

View File

@@ -0,0 +1,43 @@
query adminWorkspace(
$id: String!
$memberSkip: Int
$memberTake: Int
$memberQuery: String
) {
adminWorkspace(id: $id) {
id
public
createdAt
name
avatarKey
enableAi
enableSharing
enableUrlPreview
enableDocEmbedding
owner {
id
name
email
avatarUrl
}
memberCount
publicPageCount
snapshotCount
snapshotSize
blobCount
blobSize
sharedLinks {
docId
title
publishedAt
}
members(skip: $memberSkip, take: $memberTake, query: $memberQuery) {
id
name
email
avatarUrl
role
status
}
}
}

View File

@@ -0,0 +1,29 @@
query adminWorkspaces($filter: ListWorkspaceInput!) {
adminWorkspaces(filter: $filter) {
id
public
createdAt
name
avatarKey
enableAi
enableSharing
enableUrlPreview
enableDocEmbedding
owner {
id
name
email
avatarUrl
}
memberCount
publicPageCount
snapshotCount
snapshotSize
blobCount
blobSize
}
}
query adminWorkspacesCount($filter: ListWorkspaceInput!) {
adminWorkspacesCount(filter: $filter)
}

View File

@@ -0,0 +1,11 @@
query authSigningKeys {
authSigningKeys {
id
status
source
createdAt
retiredAt
verifyUntil
canDelete
}
}

View File

@@ -0,0 +1,3 @@
mutation createChangePasswordUrl($callbackUrl: String!, $userId: String!) {
createChangePasswordUrl(callbackUrl: $callbackUrl, userId: $userId)
}

View File

@@ -0,0 +1,3 @@
query appConfig {
appConfig
}

View File

@@ -0,0 +1,5 @@
mutation createUser($input: CreateUserInput!) {
createUser(input: $input) {
id
}
}

View File

@@ -0,0 +1,11 @@
mutation deleteAuthSigningKey($id: String!) {
deleteAuthSigningKey(id: $id) {
id
status
source
createdAt
retiredAt
verifyUntil
canDelete
}
}

View File

@@ -0,0 +1,5 @@
mutation deleteUser($id: String!) {
deleteUser(id: $id) {
success
}
}

View File

@@ -0,0 +1,6 @@
mutation disableUser($id: String!) {
banUser(id: $id) {
email
disabled
}
}

View File

@@ -0,0 +1,6 @@
mutation enableUser($id: String!) {
enableUser(id: $id) {
email
disabled
}
}

View File

@@ -0,0 +1,12 @@
query getUserByEmail($email: String!) {
userByEmail(email: $email) {
id
name
email
features
hasPassword
emailVerified
avatarUrl
disabled
}
}

View File

@@ -0,0 +1,14 @@
mutation ImportUsers($input: ImportUsersInput!) {
importUsers(input: $input) {
__typename
... on UserType {
id
name
email
}
... on UserImportFailedType {
email
error
}
}
}

View File

@@ -0,0 +1,13 @@
query listUsers($filter: ListUserInput!) {
users(filter: $filter) {
id
name
email
disabled
features
hasPassword
emailVerified
avatarUrl
}
usersCount(filter: $filter)
}

View File

@@ -0,0 +1,11 @@
mutation rotateAuthSigningKey($expectedActiveKeyId: String!) {
rotateAuthSigningKey(expectedActiveKeyId: $expectedActiveKeyId) {
id
status
source
createdAt
retiredAt
verifyUntil
canDelete
}
}

View File

@@ -0,0 +1,21 @@
mutation sendTestEmail(
$name: String!
$host: String!
$port: Int!
$sender: String!
$username: String!
$password: String!
$ignoreTLS: Boolean!
) {
sendTestEmail(
config: {
name: $name
host: $host
port: $port
sender: $sender
username: $username
password: $password
ignoreTLS: $ignoreTLS
}
)
}

View File

@@ -0,0 +1,3 @@
mutation updateAccountFeatures($userId: String!, $features: [FeatureType!]!) {
updateUserFeatures(id: $userId, features: $features)
}

View File

@@ -0,0 +1,7 @@
mutation updateAccount($id: String!, $input: ManageUserInput!) {
updateUser(id: $id, input: $input) {
id
name
email
}
}

View File

@@ -0,0 +1,3 @@
mutation updateAppConfig($updates: [UpdateAppConfigInput!]!) {
updateAppConfig(updates: $updates)
}

View File

@@ -0,0 +1,9 @@
query validateConfig($updates: [UpdateAppConfigInput!]!) {
validateAppConfig(updates: $updates) {
module
key
value
valid
error
}
}

View File

@@ -0,0 +1,7 @@
mutation deleteBlob(
$workspaceId: String!
$key: String!
$permanently: Boolean
) {
deleteBlob(workspaceId: $workspaceId, key: $key, permanently: $permanently)
}

View File

@@ -0,0 +1,10 @@
query listBlobs($workspaceId: String!) {
workspace(id: $workspaceId) {
blobs {
key
size
mime
createdAt
}
}
}

View File

@@ -0,0 +1,3 @@
mutation releaseDeletedBlobs($workspaceId: String!) {
releaseDeletedBlobs(workspaceId: $workspaceId)
}

View File

@@ -0,0 +1,3 @@
mutation setBlob($workspaceId: String!, $blob: Upload!) {
setBlob(workspaceId: $workspaceId, blob: $blob)
}

View File

@@ -0,0 +1,7 @@
mutation abortBlobUpload(
$workspaceId: String!
$key: String!
$uploadId: String!
) {
abortBlobUpload(workspaceId: $workspaceId, key: $key, uploadId: $uploadId)
}

View File

@@ -0,0 +1,13 @@
mutation completeBlobUpload(
$workspaceId: String!
$key: String!
$uploadId: String
$parts: [BlobUploadPartInput!]
) {
completeBlobUpload(
workspaceId: $workspaceId
key: $key
uploadId: $uploadId
parts: $parts
)
}

View File

@@ -0,0 +1,26 @@
mutation createBlobUpload(
$workspaceId: String!
$key: String!
$size: Int!
$mime: String!
) {
createBlobUpload(
workspaceId: $workspaceId
key: $key
size: $size
mime: $mime
) {
method
blobKey
alreadyUploaded
uploadUrl
headers
expiresAt
uploadId
partSize
uploadedParts {
partNumber
etag
}
}
}

View File

@@ -0,0 +1,14 @@
query getBlobUploadPartUrl(
$workspaceId: String!
$key: String!
$uploadId: String!
$partNumber: Int!
) {
workspace(id: $workspaceId) {
blobUploadPartUrl(key: $key, uploadId: $uploadId, partNumber: $partNumber) {
uploadUrl
headers
expiresAt
}
}
}

View File

@@ -0,0 +1,28 @@
query calendarAccounts {
currentUser {
calendarAccounts {
id
provider
providerAccountId
displayName
email
status
lastError
refreshIntervalMinutes
calendarsCount
createdAt
updatedAt
calendars {
id
accountId
provider
externalCalendarId
displayName
timezone
color
enabled
lastSyncAt
}
}
}
}

View File

@@ -0,0 +1,21 @@
query calendarEvents($workspaceId: String!, $from: DateTime!, $to: DateTime!) {
workspace(id: $workspaceId) {
calendars {
id
events(from: $from, to: $to) {
id
subscriptionId
externalEventId
recurrenceId
status
title
description
location
startAtUtc
endAtUtc
originalTimezone
allDay
}
}
}
}

View File

@@ -0,0 +1,11 @@
query calendarProviders {
serverConfig {
calendarCalDAVProviders {
id
label
requiresAppPassword
docsUrl
}
calendarProviders
}
}

View File

@@ -0,0 +1,15 @@
mutation linkCalDavAccount($input: LinkCalDAVAccountInput!) {
linkCalDAVAccount(input: $input) {
id
provider
providerAccountId
displayName
email
status
lastError
refreshIntervalMinutes
calendarsCount
createdAt
updatedAt
}
}

View File

@@ -0,0 +1,3 @@
mutation linkCalendarAccount($input: LinkCalendarAccountInput!) {
linkCalendarAccount(input: $input)
}

View File

@@ -0,0 +1,3 @@
mutation unlinkCalendarAccount($accountId: String!) {
unlinkCalendarAccount(accountId: $accountId)
}

View File

@@ -0,0 +1,21 @@
mutation updateCalendarAccount(
$accountId: String!
$refreshIntervalMinutes: Int!
) {
updateCalendarAccount(
accountId: $accountId
refreshIntervalMinutes: $refreshIntervalMinutes
) {
id
provider
providerAccountId
displayName
email
status
lastError
refreshIntervalMinutes
calendarsCount
createdAt
updatedAt
}
}

View File

@@ -0,0 +1,17 @@
mutation updateWorkspaceCalendars($input: UpdateWorkspaceCalendarsInput!) {
updateWorkspaceCalendars(input: $input) {
id
workspaceId
createdByUserId
displayNameOverride
colorOverride
enabled
items {
id
subscriptionId
sortOrder
colorOverride
enabled
}
}
}

View File

@@ -0,0 +1,19 @@
query workspaceCalendars($workspaceId: String!) {
workspace(id: $workspaceId) {
calendars {
id
workspaceId
createdByUserId
displayNameOverride
colorOverride
enabled
items {
id
subscriptionId
sortOrder
colorOverride
enabled
}
}
}
}

View File

@@ -0,0 +1,11 @@
mutation cancelSubscription(
$plan: SubscriptionPlan = Pro
$workspaceId: String
) {
cancelSubscription(plan: $plan, workspaceId: $workspaceId) {
id
status
nextBillAt
canceledAt
}
}

View File

@@ -0,0 +1,6 @@
mutation changeEmail($token: String!, $email: String!) {
changeEmail(token: $token, email: $email) {
id
email
}
}

View File

@@ -0,0 +1,7 @@
mutation changePassword(
$token: String!
$userId: String!
$newPassword: String!
) {
changePassword(token: $token, userId: $userId, newPassword: $newPassword)
}

View File

@@ -0,0 +1,26 @@
query listCommentChanges(
$workspaceId: String!
$docId: String!
$pagination: PaginationInput!
) {
workspace(id: $workspaceId) {
commentChanges(docId: $docId, pagination: $pagination) {
totalCount
edges {
cursor
node {
action
id
commentId
item
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
}

View File

@@ -0,0 +1,26 @@
mutation createComment($input: CommentCreateInput!) {
createComment(input: $input) {
id
content
resolved
createdAt
updatedAt
user {
id
name
avatarUrl
}
replies {
commentId
id
content
createdAt
updatedAt
user {
id
name
avatarUrl
}
}
}
}

View File

@@ -0,0 +1,3 @@
mutation deleteComment($id: String!) {
deleteComment(id: $id)
}

View File

@@ -0,0 +1,44 @@
query listComments(
$workspaceId: String!
$docId: String!
$pagination: PaginationInput
) {
workspace(id: $workspaceId) {
comments(docId: $docId, pagination: $pagination) {
totalCount
edges {
cursor
node {
id
content
resolved
createdAt
updatedAt
user {
id
name
avatarUrl
}
replies {
commentId
id
content
createdAt
updatedAt
user {
id
name
avatarUrl
}
}
}
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
}

View File

@@ -0,0 +1,14 @@
mutation createReply($input: ReplyCreateInput!) {
createReply(input: $input) {
commentId
id
content
createdAt
updatedAt
user {
id
name
avatarUrl
}
}
}

View File

@@ -0,0 +1,3 @@
mutation deleteReply($id: String!) {
deleteReply(id: $id)
}

View File

@@ -0,0 +1,3 @@
mutation updateReply($input: ReplyUpdateInput!) {
updateReply(input: $input)
}

View File

@@ -0,0 +1,3 @@
mutation resolveComment($input: CommentResolveInput!) {
resolveComment(input: $input)
}

View File

@@ -0,0 +1,3 @@
mutation updateComment($input: CommentUpdateInput!) {
updateComment(input: $input)
}

View File

@@ -0,0 +1,11 @@
mutation uploadCommentAttachment(
$workspaceId: String!
$docId: String!
$attachment: Upload!
) {
uploadCommentAttachment(
workspaceId: $workspaceId
docId: $docId
attachment: $attachment
)
}

View File

@@ -0,0 +1,31 @@
query getCopilotHistoryIds(
$workspaceId: String!
$pagination: PaginationInput!
$docId: String
$options: QueryChatHistoriesInput
) {
currentUser {
copilot(workspaceId: $workspaceId) {
chats(pagination: $pagination, docId: $docId, options: $options) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
cursor
node {
sessionId
pinned
messages {
id
role
createdAt
}
}
}
}
}
}
}

View File

@@ -0,0 +1,16 @@
#import "./fragments/paginated-copilot-chats.gql"
query getCopilotDocSessions(
$workspaceId: String!
$docId: String!
$pagination: PaginationInput!
$options: QueryChatHistoriesInput
) {
currentUser {
copilot(workspaceId: $workspaceId) {
chats(pagination: $pagination, docId: $docId, options: $options) {
...PaginatedCopilotChats
}
}
}
}

View File

@@ -0,0 +1,24 @@
#import "./fragments/paginated-copilot-chats.gql"
query getCopilotPinnedSessions(
$workspaceId: String!
$docId: String
$messageOrder: ChatHistoryOrder
$withPrompt: Boolean
) {
currentUser {
copilot(workspaceId: $workspaceId) {
chats(
pagination: { first: 1 }
docId: $docId
options: {
pinned: true
messageOrder: $messageOrder
withPrompt: $withPrompt
}
) {
...PaginatedCopilotChats
}
}
}
}

View File

@@ -0,0 +1,15 @@
#import "./fragments/paginated-copilot-chats.gql"
query getCopilotWorkspaceSessions(
$workspaceId: String!
$pagination: PaginationInput!
$options: QueryChatHistoriesInput
) {
currentUser {
copilot(workspaceId: $workspaceId) {
chats(pagination: $pagination, docId: null, options: $options) {
...PaginatedCopilotChats
}
}
}
}

View File

@@ -0,0 +1,16 @@
#import "./fragments/paginated-copilot-chats.gql"
query getCopilotHistories(
$workspaceId: String!
$pagination: PaginationInput!
$docId: String
$options: QueryChatHistoriesInput
) {
currentUser {
copilot(workspaceId: $workspaceId) {
chats(pagination: $pagination, docId: $docId, options: $options) {
...PaginatedCopilotChats
}
}
}
}

View File

@@ -0,0 +1,3 @@
mutation createCopilotMessage($options: CreateChatMessageInput!) {
createCopilotMessage(options: $options)
}

View File

@@ -0,0 +1,10 @@
query copilotQuota {
currentUser {
copilot {
quota {
limit
used
}
}
}
}

View File

@@ -0,0 +1,16 @@
query getCopilotRouteOptions($promptName: String!) {
currentUser {
copilot {
routeOptions(promptName: $promptName) {
routeId
defaultTargetId
choices {
id
displayName
minimumTier
available
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
mutation cleanupCopilotSession($input: DeleteSessionInput!) {
cleanupCopilotSession(options: $input)
}

View File

@@ -0,0 +1,7 @@
#import "./fragments/copilot-chat-history.gql"
mutation createCopilotSessionWithHistory($options: CreateChatSessionInput!) {
createCopilotSessionWithHistory(options: $options) {
...CopilotChatHistory
}
}

View File

@@ -0,0 +1,3 @@
mutation createCopilotSession($options: CreateChatSessionInput!) {
createCopilotSession(options: $options)
}

View File

@@ -0,0 +1,3 @@
mutation forkCopilotSession($options: ForkChatSessionInput!) {
forkCopilotSession(options: $options)
}

View File

@@ -0,0 +1,20 @@
#import "./fragments/paginated-copilot-chats.gql"
query getCopilotLatestDocSession($workspaceId: String!, $docId: String!) {
currentUser {
copilot(workspaceId: $workspaceId) {
chats(
pagination: { first: 1 }
docId: $docId
options: {
sessionOrder: desc
action: false
fork: false
withMessages: true
}
) {
...PaginatedCopilotChats
}
}
}
}

View File

@@ -0,0 +1,11 @@
#import "./fragments/paginated-copilot-chats.gql"
query getCopilotSession($workspaceId: String!, $sessionId: String!) {
currentUser {
copilot(workspaceId: $workspaceId) {
chats(pagination: { first: 1 }, options: { sessionId: $sessionId }) {
...PaginatedCopilotChats
}
}
}
}

View File

@@ -0,0 +1,23 @@
#import "./fragments/paginated-copilot-chats.gql"
query getCopilotRecentSessions(
$workspaceId: String!
$limit: Int = 10
$offset: Int = 0
) {
currentUser {
copilot(workspaceId: $workspaceId) {
chats(
pagination: { first: $limit, offset: $offset }
options: {
action: false
fork: false
sessionOrder: desc
withMessages: false
}
) {
...PaginatedCopilotChats
}
}
}
}

View File

@@ -0,0 +1,3 @@
mutation updateCopilotSession($options: UpdateChatSessionInput!) {
updateCopilotSession(options: $options)
}

View File

@@ -0,0 +1,16 @@
#import "./fragments/paginated-copilot-chats.gql"
query getCopilotSessions(
$workspaceId: String!
$pagination: PaginationInput!
$docId: String
$options: QueryChatHistoriesInput
) {
currentUser {
copilot(workspaceId: $workspaceId) {
chats(pagination: $pagination, docId: $docId, options: $options) {
...PaginatedCopilotChats
}
}
}
}

View File

@@ -0,0 +1,60 @@
query getTranscriptTask($workspaceId: String!, $taskId: String, $blobId: String) {
currentUser {
copilot(workspaceId: $workspaceId) {
transcriptTask(taskId: $taskId, blobId: $blobId) {
id
status
title
summary
sourceAudio {
blobId
mimeType
durationMs
sampleRate
channels
}
quality {
degraded
overflowCount
}
sliceManifest {
index
fileName
mimeType
startSec
durationSec
byteSize
}
normalizedSegments {
speaker
startSec
endSec
start
end
text
}
normalizedTranscript
summaryJson {
title
durationMinutes
attendees
keyPoints
actionItems {
description
owner
deadline
}
decisions
openQuestions
blockers
}
transcription {
speaker
start
end
transcription
}
}
}
}
}

View File

@@ -0,0 +1,6 @@
mutation retryTranscriptTask($workspaceId: String!, $taskId: String!) {
retryTranscriptTask(workspaceId: $workspaceId, taskId: $taskId) {
id
status
}
}

View File

@@ -0,0 +1,57 @@
mutation settleTranscriptTask($workspaceId: String!, $taskId: String!) {
settleTranscriptTask(workspaceId: $workspaceId, taskId: $taskId) {
id
status
title
summary
actions
sourceAudio {
blobId
mimeType
durationMs
sampleRate
channels
}
quality {
degraded
overflowCount
}
sliceManifest {
index
fileName
mimeType
startSec
durationSec
byteSize
}
normalizedSegments {
speaker
startSec
endSec
start
end
text
}
normalizedTranscript
summaryJson {
title
durationMinutes
attendees
keyPoints
actionItems {
description
owner
deadline
}
decisions
openQuestions
blockers
}
transcription {
speaker
start
end
transcription
}
}
}

View File

@@ -0,0 +1,18 @@
mutation submitTranscriptTask(
$workspaceId: String!
$blobId: String!
$blob: Upload
$blobs: [Upload!]
$input: SubmitAudioTranscriptionInput
) {
submitTranscriptTask(
blob: $blob
blobs: $blobs
blobId: $blobId
workspaceId: $workspaceId
input: $input
) {
id
status
}
}

View File

@@ -0,0 +1,9 @@
mutation addWorkspaceArtifact($workspaceId: String!, $blob: Upload!) {
addWorkspaceArtifact(workspaceId: $workspaceId, blob: $blob) {
artifactId
contentHash
mediaType
size
createdAt
}
}

View File

@@ -0,0 +1,27 @@
query getWorkspaceArtifacts(
$workspaceId: String!
$pagination: PaginationInput!
) {
workspace(id: $workspaceId) {
embedding {
artifacts(pagination: $pagination) {
totalCount
pageInfo {
endCursor
hasNextPage
}
edges {
node {
artifactId
contentHash
fileName
embeddingStatus
mediaType
size
createdAt
}
}
}
}
}
}

View File

@@ -0,0 +1,6 @@
mutation removeWorkspaceArtifact(
$workspaceId: String!
$artifactId: String!
) {
removeWorkspaceArtifact(workspaceId: $workspaceId, artifactId: $artifactId)
}

View File

@@ -0,0 +1,6 @@
mutation addWorkspaceEmbeddingIgnoredDocs(
$workspaceId: String!
$add: [String!]!
) {
updateWorkspaceEmbeddingIgnoredDocs(workspaceId: $workspaceId, add: $add)
}

View File

@@ -0,0 +1,10 @@
query getAllWorkspaceEmbeddingIgnoredDocs($workspaceId: String!) {
workspace(id: $workspaceId) {
embedding {
allIgnoredDocs {
docId
createdAt
}
}
}
}

View File

@@ -0,0 +1,28 @@
query getWorkspaceEmbeddingIgnoredDocs(
$workspaceId: String!
$pagination: PaginationInput!
) {
workspace(id: $workspaceId) {
embedding {
ignoredDocs(pagination: $pagination) {
totalCount
pageInfo {
endCursor
hasNextPage
}
edges {
node {
docId
createdAt
docCreatedAt
docUpdatedAt
title
createdBy
createdByAvatar
updatedBy
}
}
}
}
}
}

View File

@@ -0,0 +1,9 @@
mutation removeWorkspaceEmbeddingIgnoredDocs(
$workspaceId: String!
$remove: [String!]!
) {
updateWorkspaceEmbeddingIgnoredDocs(
workspaceId: $workspaceId
remove: $remove
)
}

View File

@@ -0,0 +1,3 @@
mutation createCheckoutSession($input: CreateCheckoutSessionInput!) {
createCheckoutSession(input: $input)
}

View File

@@ -0,0 +1,3 @@
mutation createCustomerPortal {
createCustomerPortal
}

View File

@@ -0,0 +1,3 @@
mutation createSelfhostCustomerPortal($workspaceId: String!) {
createSelfhostWorkspaceCustomerPortal(workspaceId: $workspaceId)
}

View File

@@ -0,0 +1,7 @@
mutation createWorkspace {
createWorkspace {
id
public
createdAt
}
}

View File

@@ -0,0 +1,5 @@
mutation deleteAccount {
deleteAccount {
success
}
}

View File

@@ -0,0 +1,3 @@
mutation deleteWorkspace($id: String!) {
deleteWorkspace(id: $id)
}

View File

@@ -0,0 +1,29 @@
query getDocRolePermissions($workspaceId: String!, $docId: String!) {
workspace(id: $workspaceId) {
doc(docId: $docId) {
permissions {
Doc_Copy
Doc_Analytics_Read
Doc_Analytics_Viewers_Read
Doc_Delete
Doc_Duplicate
Doc_Properties_Read
Doc_Properties_Update
Doc_Publish
Doc_Read
Doc_Restore
Doc_TransferOwner
Doc_Trash
Doc_Update
Doc_Users_Manage
Doc_Users_Read
Doc_Comments_Create
Doc_Comments_Moderate
Doc_Comments_Read
Doc_History_Read
Doc_Preview
Doc_Unpublish
}
}
}
}

View File

@@ -0,0 +1,28 @@
fragment CopilotChatHistory on CopilotHistories {
sessionId
workspaceId
docId
parentSessionId
promptName
action
pinned
title
messages {
id
role
content
attachments
scopeSnapshot
streamObjects {
type
textDelta
toolCallId
toolName
args
result
}
createdAt
}
createdAt
updatedAt
}

View File

@@ -0,0 +1,5 @@
fragment CredentialsRequirements on CredentialsRequirementType {
password {
...PasswordLimits
}
}

View File

@@ -0,0 +1,16 @@
#import "./copilot-chat-history.gql"
fragment PaginatedCopilotChats on PaginatedCopilotHistoriesType {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
cursor
node {
...CopilotChatHistory
}
}
}

View File

@@ -0,0 +1,4 @@
fragment PasswordLimits on PasswordLimitsType {
minLength
maxLength
}

View File

@@ -0,0 +1,3 @@
mutation generateLicenseKey($sessionId: String!) {
generateLicenseKey(sessionId: $sessionId)
}

Some files were not shown because too many files have changed in this diff Show More