Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added graphql/server/.gitignore
Empty file.
32,215 changes: 32,215 additions & 0 deletions graphql/server/codegen/schema.graphql

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions graphql/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
"lint": "eslint . --fix",
"test": "jest --passWithNoTests",
"test:watch": "jest --watch",
"bucket:create": "ts-node src/scripts/create-bucket.ts"
"bucket:create": "ts-node src/scripts/create-bucket.ts",
"codegen:schema": "ts-node src/scripts/codegen-schema.ts",
"codegen": "npm run codegen:schema && graphql-codegen generate-orm --schema codegen/schema.graphql --output src/codegen/orm"
},
"keywords": [
"server",
Expand Down Expand Up @@ -74,13 +76,15 @@
},
"devDependencies": {
"@aws-sdk/client-s3": "^3.958.0",
"@constructive-io/graphql-codegen": "^2.23.2",
"@types/cors": "^2.8.17",
"@types/express": "^5.0.6",
"@types/graphql-upload": "^8.0.12",
"@types/pg": "^8.16.0",
"@types/request-ip": "^0.0.41",
"graphile-test": "^2.13.6",
"makage": "^0.1.10",
"nodemon": "^3.1.10",
"ts-node": "^10.9.2"
}
}
}
114 changes: 114 additions & 0 deletions graphql/server/src/codegen/orm/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* ORM Client - Runtime GraphQL executor
* @generated by @constructive-io/graphql-codegen
* DO NOT EDIT - changes will be overwritten
*/

export interface OrmClientConfig {
endpoint: string;
headers?: Record<string, string>;
}

export interface GraphQLError {
message: string;
locations?: { line: number; column: number }[];
path?: (string | number)[];
extensions?: Record<string, unknown>;
}

/**
* Error thrown when GraphQL request fails
*/
export class GraphQLRequestError extends Error {
constructor(
public readonly errors: GraphQLError[],
public readonly data: unknown = null
) {
const messages = errors.map((e) => e.message).join('; ');
super(`GraphQL Error: ${messages}`);
this.name = 'GraphQLRequestError';
}
}

/**
* Discriminated union for query results
* Use .ok to check success, or use .unwrap() to get data or throw
*/
export type QueryResult<T> =
| { ok: true; data: T; errors: undefined }
| { ok: false; data: null; errors: GraphQLError[] };

/**
* Legacy QueryResult type for backwards compatibility
* @deprecated Use QueryResult discriminated union instead
*/
export interface LegacyQueryResult<T> {
data: T | null;
errors?: GraphQLError[];
}

export class OrmClient {
private endpoint: string;
private headers: Record<string, string>;

constructor(config: OrmClientConfig) {
this.endpoint = config.endpoint;
this.headers = config.headers ?? {};
}

async execute<T>(
document: string,
variables?: Record<string, unknown>
): Promise<QueryResult<T>> {
const response = await fetch(this.endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
...this.headers,
},
body: JSON.stringify({
query: document,
variables: variables ?? {},
}),
});

if (!response.ok) {
return {
ok: false,
data: null,
errors: [
{ message: `HTTP ${response.status}: ${response.statusText}` },
],
};
}

const json = (await response.json()) as {
data?: T;
errors?: GraphQLError[];
};

// Return discriminated union based on presence of errors
if (json.errors && json.errors.length > 0) {
return {
ok: false,
data: null,
errors: json.errors,
};
}

return {
ok: true,
data: json.data as T,
errors: undefined,
};
}

setHeaders(headers: Record<string, string>): void {
this.headers = { ...this.headers, ...headers };
}

getEndpoint(): string {
return this.endpoint;
}
}
167 changes: 167 additions & 0 deletions graphql/server/src/codegen/orm/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/**
* ORM Client - createClient factory
* @generated by @constructive-io/graphql-codegen
* DO NOT EDIT - changes will be overwritten
*/
import { OrmClient, type OrmClientConfig } from './client';
import { CheckConstraintModel } from './models/checkConstraint';
import { SchemaModel } from './models/schema';
import { TableModel } from './models/table';
import { FieldModel } from './models/field';
import { DenormalizedTableFieldModel } from './models/denormalizedTableField';
import { FieldModuleModel } from './models/fieldModule';
import { MembershipsModuleModel } from './models/membershipsModule';
import { ForeignKeyConstraintModel } from './models/foreignKeyConstraint';
import { FullTextSearchModel } from './models/fullTextSearch';
import { IndexModel } from './models/index';
import { LimitFunctionModel } from './models/limitFunction';
import { PolicyModel } from './models/policy';
import { PrimaryKeyConstraintModel } from './models/primaryKeyConstraint';
import { RlsFunctionModel } from './models/rlsFunction';
import { TableGrantModel } from './models/tableGrant';
import { TriggerModel } from './models/trigger';
import { UniqueConstraintModel } from './models/uniqueConstraint';
import { ConnectedAccountsModuleModel } from './models/connectedAccountsModule';
import { CryptoAddressesModuleModel } from './models/cryptoAddressesModule';
import { CryptoAuthModuleModel } from './models/cryptoAuthModule';
import { EmailsModuleModel } from './models/emailsModule';
import { EncryptedSecretsModuleModel } from './models/encryptedSecretsModule';
import { InvitesModuleModel } from './models/invitesModule';
import { LevelsModuleModel } from './models/levelsModule';
import { LimitsModuleModel } from './models/limitsModule';
import { MembershipTypesModuleModel } from './models/membershipTypesModule';
import { PermissionsModuleModel } from './models/permissionsModule';
import { PhoneNumbersModuleModel } from './models/phoneNumbersModule';
import { ProfilesModuleModel } from './models/profilesModule';
import { SecretsModuleModel } from './models/secretsModule';
import { TokensModuleModel } from './models/tokensModule';
import { UsersModuleModel } from './models/usersModule';
import { HierarchyModuleModel } from './models/hierarchyModule';
import { SchemaGrantModel } from './models/schemaGrant';
import { ApiSchemaModel } from './models/apiSchema';
import { ApiExtensionModel } from './models/apiExtension';
import { ApiModuleModel } from './models/apiModule';
import { DomainModel } from './models/domain';
import { SiteMetadatumModel } from './models/siteMetadatum';
import { SiteModuleModel } from './models/siteModule';
import { SiteThemeModel } from './models/siteTheme';
import { RlsModuleModel } from './models/rlsModule';
import { UserAuthModuleModel } from './models/userAuthModule';
import { UuidModuleModel } from './models/uuidModule';
import { DatabaseExtensionModel } from './models/databaseExtension';
import { ProcedureModel } from './models/procedure';
import { TriggerFunctionModel } from './models/triggerFunction';
import { ApiModel } from './models/api';
import { SiteModel } from './models/site';
import { AppModel } from './models/app';
import { DefaultIdsModuleModel } from './models/defaultIdsModule';
import { DatabaseProvisionModel } from './models/databaseProvision';
import { ModuleModel } from './models/module';
import { ModuleFieldModel } from './models/moduleField';
import { ModuleInputRecordModel } from './models/moduleInputRecord';
import { ModuleOutputModel } from './models/moduleOutput';
import { DatabaseModel } from './models/database';
import { ExtensionModel } from './models/extension';
import { ModuleDefinitionModel } from './models/moduleDefinition';
import { createQueryOperations } from './query';
import { createMutationOperations } from './mutation';

// Re-export types and classes
export type { OrmClientConfig, QueryResult, GraphQLError } from './client';
export { GraphQLRequestError } from './client';
export { QueryBuilder } from './query-builder';
export * from './select-types';

// ============================================================================
// Client Factory
// ============================================================================
/**
* Create an ORM client instance
*
* @example
* ```typescript
* const db = createClient({
* endpoint: 'https://api.example.com/graphql',
* headers: { Authorization: 'Bearer token' },
* });
*
* // Query users
* const users = await db.user.findMany({
* select: { id: true, name: true },
* first: 10,
* }).execute();
*
* // Create a user
* const newUser = await db.user.create({
* data: { name: 'John', email: 'john@example.com' },
* select: { id: true },
* }).execute();
* ```
*/
export function createClient(config: OrmClientConfig) {
const client = new OrmClient(config);

return {
checkConstraint: new CheckConstraintModel(client),
schema: new SchemaModel(client),
table: new TableModel(client),
field: new FieldModel(client),
denormalizedTableField: new DenormalizedTableFieldModel(client),
fieldModule: new FieldModuleModel(client),
membershipsModule: new MembershipsModuleModel(client),
foreignKeyConstraint: new ForeignKeyConstraintModel(client),
fullTextSearch: new FullTextSearchModel(client),
index: new IndexModel(client),
limitFunction: new LimitFunctionModel(client),
policy: new PolicyModel(client),
primaryKeyConstraint: new PrimaryKeyConstraintModel(client),
rlsFunction: new RlsFunctionModel(client),
tableGrant: new TableGrantModel(client),
trigger: new TriggerModel(client),
uniqueConstraint: new UniqueConstraintModel(client),
connectedAccountsModule: new ConnectedAccountsModuleModel(client),
cryptoAddressesModule: new CryptoAddressesModuleModel(client),
cryptoAuthModule: new CryptoAuthModuleModel(client),
emailsModule: new EmailsModuleModel(client),
encryptedSecretsModule: new EncryptedSecretsModuleModel(client),
invitesModule: new InvitesModuleModel(client),
levelsModule: new LevelsModuleModel(client),
limitsModule: new LimitsModuleModel(client),
membershipTypesModule: new MembershipTypesModuleModel(client),
permissionsModule: new PermissionsModuleModel(client),
phoneNumbersModule: new PhoneNumbersModuleModel(client),
profilesModule: new ProfilesModuleModel(client),
secretsModule: new SecretsModuleModel(client),
tokensModule: new TokensModuleModel(client),
usersModule: new UsersModuleModel(client),
hierarchyModule: new HierarchyModuleModel(client),
schemaGrant: new SchemaGrantModel(client),
apiSchema: new ApiSchemaModel(client),
apiExtension: new ApiExtensionModel(client),
apiModule: new ApiModuleModel(client),
domain: new DomainModel(client),
siteMetadatum: new SiteMetadatumModel(client),
siteModule: new SiteModuleModel(client),
siteTheme: new SiteThemeModel(client),
rlsModule: new RlsModuleModel(client),
userAuthModule: new UserAuthModuleModel(client),
uuidModule: new UuidModuleModel(client),
databaseExtension: new DatabaseExtensionModel(client),
procedure: new ProcedureModel(client),
triggerFunction: new TriggerFunctionModel(client),
api: new ApiModel(client),
site: new SiteModel(client),
app: new AppModel(client),
defaultIdsModule: new DefaultIdsModuleModel(client),
databaseProvision: new DatabaseProvisionModel(client),
module: new ModuleModel(client),
moduleField: new ModuleFieldModel(client),
moduleInputRecord: new ModuleInputRecordModel(client),
moduleOutput: new ModuleOutputModel(client),
database: new DatabaseModel(client),
extension: new ExtensionModel(client),
moduleDefinition: new ModuleDefinitionModel(client),
query: createQueryOperations(client),
mutation: createMutationOperations(client),
};
}
Loading