query-2jz
Version:
Query-2jz: A GraphQL alternative with faster performance and simpler use
243 lines (213 loc) • 5.75 kB
text/typescript
import { Query2jz, Query2jzConfig, Query2jzModel } from '../index';
/**
* Strapi Adapter for Query2jz
*/
export class Query2jzStrapiAdapter {
private qryn: Query2jz;
constructor(config: Query2jzConfig, models: Query2jzModel[] = []) {
this.qryn = new Query2jz(config, models);
}
/**
* Initialize the adapter
*/
async initialize(): Promise<void> {
await this.qryn.initialize();
}
/**
* Get Query2jz instance
*/
getQuery2jz(): Query2jz {
return this.qryn;
}
/**
* Register Strapi routes
*/
registerRoutes(strapi: any): void {
// Health check
strapi.server.routes([
{
method: 'GET',
path: '/health',
handler: 'Query2jzController.health',
config: {
policies: []
}
},
{
method: 'GET',
path: '/api/qryn/:model',
handler: 'Query2jzController.query',
config: {
policies: []
}
},
{
method: 'POST',
path: '/api/qryn/:model',
handler: 'Query2jzController.mutate',
config: {
policies: []
}
},
{
method: 'GET',
path: '/api/qryn/stats',
handler: 'Query2jzController.stats',
config: {
policies: []
}
},
{
method: 'POST',
path: '/api/qryn/generate-types',
handler: 'Query2jzController.generateTypes',
config: {
policies: []
}
}
]);
}
}
/**
* Strapi controller
*/
export class Query2jzController {
private qrynAdapter: Query2jzStrapiAdapter;
constructor(qrynAdapter: Query2jzStrapiAdapter) {
this.qrynAdapter = qrynAdapter;
}
async health(ctx: any): Promise<void> {
try {
const stats = this.qrynAdapter.getQuery2jz().getStats();
ctx.body = {
status: 'healthy',
timestamp: new Date().toISOString(),
...stats
};
} catch (error) {
ctx.status = 500;
ctx.body = {
status: 'unhealthy',
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async query(ctx: any): Promise<void> {
try {
const model = ctx.params.model;
const query = this.parseQueryParams(ctx.query);
const result = await this.qrynAdapter.getQuery2jz().query(query, model);
if (result.meta?.etag) {
ctx.set('ETag', result.meta.etag);
}
if (result.meta?.lastModified) {
ctx.set('Last-Modified', result.meta.lastModified);
}
ctx.set('Cache-Control', 'public, max-age=300');
ctx.body = result;
} catch (error) {
ctx.status = 500;
ctx.body = {
error: 'Query execution failed',
message: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async mutate(ctx: any): Promise<void> {
try {
const model = ctx.params.model;
const mutation = ctx.request.body;
if (!mutation.operation) {
ctx.status = 400;
ctx.body = {
error: 'Invalid mutation',
message: 'Operation is required'
};
return;
}
const result = await this.qrynAdapter.getQuery2jz().mutate(mutation, model);
ctx.set('Cache-Control', 'no-cache');
ctx.body = result;
} catch (error) {
ctx.status = 500;
ctx.body = {
error: 'Mutation execution failed',
message: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async stats(ctx: any): Promise<void> {
try {
const stats = this.qrynAdapter.getQuery2jz().getStats();
ctx.body = stats;
} catch (error) {
ctx.status = 500;
ctx.body = {
error: 'Failed to get statistics',
message: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async generateTypes(ctx: any): Promise<void> {
try {
const { outputDir } = ctx.request.body;
this.qrynAdapter.getQuery2jz().generateTypes(outputDir);
ctx.body = {
message: 'Types generated successfully',
outputDir: outputDir || './generated'
};
} catch (error) {
ctx.status = 500;
ctx.body = {
error: 'Type generation failed',
message: error instanceof Error ? error.message : 'Unknown error'
};
}
}
private parseQueryParams(queryParams: any): any {
const query: any = {};
if (queryParams.select) {
try {
query.select = JSON.parse(queryParams.select);
} catch {
query.select = {};
}
}
if (queryParams.where) {
try {
query.where = JSON.parse(queryParams.where);
} catch {
query.where = {};
}
}
if (queryParams.orderBy) {
try {
query.orderBy = JSON.parse(queryParams.orderBy);
} catch {
query.orderBy = {};
}
}
if (queryParams.limit) {
query.limit = parseInt(queryParams.limit);
}
if (queryParams.offset) {
query.offset = parseInt(queryParams.offset);
}
if (queryParams.live === 'true') {
query.live = true;
}
return query;
}
}
/**
* Strapi plugin factory
*/
export function createQuery2jzPlugin(config: Query2jzConfig, models: Query2jzModel[] = []) {
const adapter = new Query2jzStrapiAdapter(config, models);
return {
adapter,
controller: Query2jzController,
registerRoutes: adapter.registerRoutes.bind(adapter),
initialize: () => adapter.initialize()
};
}