mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
Generate TypeScript types for the Data Connector reference agent from the OpenAPI schema
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4855 GitOrigin-RevId: 4cc09d6706e67c69fbbedef72ff816365b9f7b4e
This commit is contained in:
parent
4b2ca2ea63
commit
59ffce9ac1
@ -32,8 +32,8 @@ constraints: any.Cabal ==3.2.1.0,
|
|||||||
any.attoparsec-iso8601 ==1.0.2.1,
|
any.attoparsec-iso8601 ==1.0.2.1,
|
||||||
any.authenticate-oauth ==1.7,
|
any.authenticate-oauth ==1.7,
|
||||||
any.auto-update ==0.1.6,
|
any.auto-update ==0.1.6,
|
||||||
any.autodocodec ==0.1.0.0,
|
any.autodocodec ==0.1.0.1,
|
||||||
any.autodocodec-openapi3 ==0.2.0.0,
|
any.autodocodec-openapi3 ==0.2.1.0,
|
||||||
any.barbies ==2.0.3.1,
|
any.barbies ==2.0.3.1,
|
||||||
any.base ==4.14.3.0,
|
any.base ==4.14.3.0,
|
||||||
any.base-compat ==0.11.2,
|
any.base-compat ==0.11.2,
|
||||||
@ -352,4 +352,4 @@ constraints: any.Cabal ==3.2.1.0,
|
|||||||
any.xml-types ==0.3.8,
|
any.xml-types ==0.3.8,
|
||||||
any.yaml ==0.11.7.0,
|
any.yaml ==0.11.7.0,
|
||||||
any.zlib ==0.6.2.3,
|
any.zlib ==0.6.2.3,
|
||||||
index-state: hackage.haskell.org 2022-06-13T15:16:34Z
|
index-state: hackage.haskell.org 2022-06-20T06:51:52Z
|
||||||
|
@ -210,7 +210,7 @@ Notice that the names of tables and columns are used in the metadata document to
|
|||||||
|
|
||||||
#### Type definitions
|
#### Type definitions
|
||||||
|
|
||||||
The `SchemaResponse` TypeScript type from [the reference implementation](./reference/src/types/schema.ts) describes the valid response body for the `GET /schema` endpoint.
|
The `SchemaResponse` TypeScript type from [the reference implementation](./reference/src/types/index.ts) describes the valid response body for the `GET /schema` endpoint.
|
||||||
|
|
||||||
### Responding to queries
|
### Responding to queries
|
||||||
|
|
||||||
@ -672,4 +672,4 @@ The key point of interest here is in the `where` field where we are comparing be
|
|||||||
|
|
||||||
#### Type Definitions
|
#### Type Definitions
|
||||||
|
|
||||||
The `QueryRequest` TypeScript type in the [reference implementation](./reference/src/types/query.ts) describes the valid request body payloads which may be passed to the `POST /query` endpoint. The response body structure is captured by the `QueryResponse` type.
|
The `QueryRequest` TypeScript type in the [reference implementation](./reference/src/types/index.ts) describes the valid request body payloads which may be passed to the `POST /query` endpoint. The response body structure is captured by the `QueryResponse` type.
|
||||||
|
1018
dc-agents/reference/package-lock.json
generated
1018
dc-agents/reference/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -18,12 +18,12 @@
|
|||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"start": "ts-node ./src/index.ts",
|
"start": "ts-node ./src/index.ts",
|
||||||
"start-no-typecheck": "ts-node --transpileOnly ./src/index.ts",
|
"start-no-typecheck": "ts-node --transpileOnly ./src/index.ts",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"generate-types": "./scripts/generate-types.sh"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/cors": "^7.0.0",
|
"@fastify/cors": "^7.0.0",
|
||||||
"fastify": "^3.29.0",
|
"fastify": "^3.29.0",
|
||||||
"openapi3-ts": "^2.0.2",
|
|
||||||
"pino-pretty": "^8.0.0",
|
"pino-pretty": "^8.0.0",
|
||||||
"xml2js": "^0.4.23"
|
"xml2js": "^0.4.23"
|
||||||
},
|
},
|
||||||
@ -31,6 +31,7 @@
|
|||||||
"@tsconfig/node16": "^1.0.2",
|
"@tsconfig/node16": "^1.0.2",
|
||||||
"@types/node": "^16.11.38",
|
"@types/node": "^16.11.38",
|
||||||
"@types/xml2js": "^0.4.11",
|
"@types/xml2js": "^0.4.11",
|
||||||
|
"openapi-typescript-codegen": "^0.23.0",
|
||||||
"ts-node": "^10.8.1",
|
"ts-node": "^10.8.1",
|
||||||
"typescript": "^4.7.3"
|
"typescript": "^4.7.3"
|
||||||
}
|
}
|
||||||
|
21
dc-agents/reference/scripts/generate-types.sh
Executable file
21
dc-agents/reference/scripts/generate-types.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PROJECT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." >/dev/null 2>&1 && pwd )" # ... https://stackoverflow.com/a/246128/176841
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
|
TYPES_DIR="./src/types"
|
||||||
|
SCHEMA_FILE="$TYPES_DIR/agent.openapi.json"
|
||||||
|
|
||||||
|
mkdir -p $TYPES_DIR
|
||||||
|
|
||||||
|
if [ ! -f $SCHEMA_FILE ] ; then
|
||||||
|
echo "$SCHEMA_FILE does not exist, re-generating it using the agent test suite"
|
||||||
|
cabal run test:tests-dc-api -- export-openapi-spec | tail -n 1 | jq > $SCHEMA_FILE
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Deleting existing generated model..."
|
||||||
|
rm -rf "$TYPES_DIR/models"
|
||||||
|
rm -f "$TYPES_DIR/index.ts"
|
||||||
|
echo "Generating model from $SCHEMA_FILE..."
|
||||||
|
openapi --useUnionTypes --input $SCHEMA_FILE --output $TYPES_DIR --exportServices false --exportCore false --indent 2
|
@ -1,17 +1,7 @@
|
|||||||
import { ConfigSchemaResponse, configSchema } from "./config"
|
import { configSchema } from "./config"
|
||||||
|
import { CapabilitiesResponse } from "./types"
|
||||||
export type Relationships = {}
|
|
||||||
|
|
||||||
export type Capabilities = {
|
|
||||||
relationships: Relationships
|
|
||||||
}
|
|
||||||
|
|
||||||
export type CapabilitiesResponse = {
|
|
||||||
capabilities: Capabilities,
|
|
||||||
configSchemas: ConfigSchemaResponse,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const capabilitiesResponse: CapabilitiesResponse = {
|
export const capabilitiesResponse: CapabilitiesResponse = {
|
||||||
capabilities: { relationships: {}},
|
capabilities: { relationships: {} },
|
||||||
configSchemas: configSchema
|
configSchemas: configSchema
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
import { FastifyRequest } from "fastify"
|
import { FastifyRequest } from "fastify"
|
||||||
import { SchemaObject } from "openapi3-ts"
|
import { ConfigSchemaResponse } from "./types"
|
||||||
|
|
||||||
export type Config = {
|
export type Config = {
|
||||||
tables: String[] | null
|
tables: String[] | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ConfigSchemaResponse = {
|
|
||||||
configSchema: SchemaObject,
|
|
||||||
otherSchemas: { [schemaName: string]: SchemaObject },
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getConfig = (request: FastifyRequest): Config => {
|
export const getConfig = (request: FastifyRequest): Config => {
|
||||||
const configHeader = request.headers["x-hasura-dataconnector-config"];
|
const configHeader = request.headers["x-hasura-dataconnector-config"];
|
||||||
const rawConfigJson = Array.isArray(configHeader) ? configHeader[0] : configHeader ?? "{}";
|
const rawConfigJson = Array.isArray(configHeader) ? configHeader[0] : configHeader ?? "{}";
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { SchemaResponse, ScalarType } from "../types/schema"
|
import { SchemaResponse } from "../types"
|
||||||
import { Config } from "../config";
|
import { Config } from "../config";
|
||||||
import xml2js from "xml2js"
|
import xml2js from "xml2js"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
@ -43,13 +43,13 @@ const schema: SchemaResponse = {
|
|||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
name: "ArtistId",
|
name: "ArtistId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Artist primary key identifier"
|
description: "Artist primary key identifier"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Name",
|
name: "Name",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The name of the artist"
|
description: "The name of the artist"
|
||||||
}
|
}
|
||||||
@ -62,19 +62,19 @@ const schema: SchemaResponse = {
|
|||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
name: "AlbumId",
|
name: "AlbumId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Album primary key identifier"
|
description: "Album primary key identifier"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Title",
|
name: "Title",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The title of the album"
|
description: "The title of the album"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ArtistId",
|
name: "ArtistId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The ID of the artist that created this album"
|
description: "The ID of the artist that created this album"
|
||||||
}
|
}
|
||||||
@ -87,79 +87,79 @@ const schema: SchemaResponse = {
|
|||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
name: "CustomerId",
|
name: "CustomerId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Customer primary key identifier"
|
description: "Customer primary key identifier"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "FirstName",
|
name: "FirstName",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The customer's first name"
|
description: "The customer's first name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "LastName",
|
name: "LastName",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The customer's last name"
|
description: "The customer's last name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Company",
|
name: "Company",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The customer's company name"
|
description: "The customer's company name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Address",
|
name: "Address",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The customer's address line (street number, street)"
|
description: "The customer's address line (street number, street)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "City",
|
name: "City",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The customer's address city"
|
description: "The customer's address city"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "State",
|
name: "State",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The customer's address state"
|
description: "The customer's address state"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Country",
|
name: "Country",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The customer's address country"
|
description: "The customer's address country"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "PostalCode",
|
name: "PostalCode",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The customer's address postal code"
|
description: "The customer's address postal code"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Phone",
|
name: "Phone",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The customer's phone number"
|
description: "The customer's phone number"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Fax",
|
name: "Fax",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The customer's fax number"
|
description: "The customer's fax number"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Email",
|
name: "Email",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The customer's email address"
|
description: "The customer's email address"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "SupportRepId",
|
name: "SupportRepId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The ID of the Employee who is this customer's support representative"
|
description: "The ID of the Employee who is this customer's support representative"
|
||||||
}
|
}
|
||||||
@ -172,85 +172,85 @@ const schema: SchemaResponse = {
|
|||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
name: "EmployeeId",
|
name: "EmployeeId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Employee primary key identifier"
|
description: "Employee primary key identifier"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "FirstName",
|
name: "FirstName",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The employee's first name"
|
description: "The employee's first name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "LastName",
|
name: "LastName",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The employee's last name"
|
description: "The employee's last name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Title",
|
name: "Title",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The employee's job title"
|
description: "The employee's job title"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "BirthDate",
|
name: "BirthDate",
|
||||||
type: ScalarType.String, // Ought to be DateTime but we don't have a type for this yet
|
type: "string", // Ought to be DateTime but we don't have a type for this yet
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The employee's birth date"
|
description: "The employee's birth date"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "HireDate",
|
name: "HireDate",
|
||||||
type: ScalarType.String, // Ought to be DateTime but we don't have a type for this yet
|
type: "string", // Ought to be DateTime but we don't have a type for this yet
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The employee's birth date"
|
description: "The employee's birth date"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Address",
|
name: "Address",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The employee's address line (street number, street)"
|
description: "The employee's address line (street number, street)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "City",
|
name: "City",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The employee's address city"
|
description: "The employee's address city"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "State",
|
name: "State",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The employee's address state"
|
description: "The employee's address state"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Country",
|
name: "Country",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The employee's address country"
|
description: "The employee's address country"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "PostalCode",
|
name: "PostalCode",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The employee's address postal code"
|
description: "The employee's address postal code"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Phone",
|
name: "Phone",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The employee's phone number"
|
description: "The employee's phone number"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Fax",
|
name: "Fax",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The employee's fax number"
|
description: "The employee's fax number"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Email",
|
name: "Email",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The employee's email address"
|
description: "The employee's email address"
|
||||||
},
|
},
|
||||||
@ -263,13 +263,13 @@ const schema: SchemaResponse = {
|
|||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
name: "GenreId",
|
name: "GenreId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Genre primary key identifier"
|
description: "Genre primary key identifier"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Name",
|
name: "Name",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The name of the genre"
|
description: "The name of the genre"
|
||||||
}
|
}
|
||||||
@ -282,55 +282,55 @@ const schema: SchemaResponse = {
|
|||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
name: "InvoiceId",
|
name: "InvoiceId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Invoice primary key identifier"
|
description: "Invoice primary key identifier"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "CustomerId",
|
name: "CustomerId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "ID of the customer who bought the music"
|
description: "ID of the customer who bought the music"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "InvoiceDate",
|
name: "InvoiceDate",
|
||||||
type: ScalarType.String, // Ought to be DateTime but we don't have a type for this yet
|
type: "string", // Ought to be DateTime but we don't have a type for this yet
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Date of the invoice"
|
description: "Date of the invoice"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "BillingAddress",
|
name: "BillingAddress",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The invoice's billing address line (street number, street)"
|
description: "The invoice's billing address line (street number, street)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "BillingCity",
|
name: "BillingCity",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The invoice's billing address city"
|
description: "The invoice's billing address city"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "BillingState",
|
name: "BillingState",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The invoice's billing address state"
|
description: "The invoice's billing address state"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "BillingCountry",
|
name: "BillingCountry",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The invoice's billing address country"
|
description: "The invoice's billing address country"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "BillingPostalCode",
|
name: "BillingPostalCode",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The invoice's billing address postal code"
|
description: "The invoice's billing address postal code"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Total",
|
name: "Total",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The total amount due on the invoice"
|
description: "The total amount due on the invoice"
|
||||||
},
|
},
|
||||||
@ -343,31 +343,31 @@ const schema: SchemaResponse = {
|
|||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
name: "InvoiceLineId",
|
name: "InvoiceLineId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Invoice Line primary key identifier"
|
description: "Invoice Line primary key identifier"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "InvoiceId",
|
name: "InvoiceId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "ID of the invoice the line belongs to"
|
description: "ID of the invoice the line belongs to"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "TrackId",
|
name: "TrackId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "ID of the music track being purchased"
|
description: "ID of the music track being purchased"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "UnitPrice",
|
name: "UnitPrice",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Price of each individual track unit"
|
description: "Price of each individual track unit"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Quantity",
|
name: "Quantity",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Quantity of the track purchased"
|
description: "Quantity of the track purchased"
|
||||||
},
|
},
|
||||||
@ -380,13 +380,13 @@ const schema: SchemaResponse = {
|
|||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
name: "MediaTypeId",
|
name: "MediaTypeId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Media Type primary key identifier"
|
description: "Media Type primary key identifier"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Name",
|
name: "Name",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The name of the media type format"
|
description: "The name of the media type format"
|
||||||
},
|
},
|
||||||
@ -399,13 +399,13 @@ const schema: SchemaResponse = {
|
|||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
name: "PlaylistId",
|
name: "PlaylistId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "Playlist primary key identifier"
|
description: "Playlist primary key identifier"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Name",
|
name: "Name",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The name of the playlist"
|
description: "The name of the playlist"
|
||||||
},
|
},
|
||||||
@ -419,13 +419,13 @@ const schema: SchemaResponse = {
|
|||||||
// columns: [
|
// columns: [
|
||||||
// {
|
// {
|
||||||
// name: "PlaylistId",
|
// name: "PlaylistId",
|
||||||
// type: ScalarType.Number,
|
// type: "number",
|
||||||
// nullable: false,
|
// nullable: false,
|
||||||
// description: "The ID of the playlist"
|
// description: "The ID of the playlist"
|
||||||
// },
|
// },
|
||||||
// {
|
// {
|
||||||
// name: "TrackId",
|
// name: "TrackId",
|
||||||
// type: ScalarType.Number,
|
// type: "number",
|
||||||
// nullable: true,
|
// nullable: true,
|
||||||
// description: "The ID of the track"
|
// description: "The ID of the track"
|
||||||
// },
|
// },
|
||||||
@ -438,55 +438,55 @@ const schema: SchemaResponse = {
|
|||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
name: "TrackId",
|
name: "TrackId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The ID of the track"
|
description: "The ID of the track"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Name",
|
name: "Name",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The name of the track"
|
description: "The name of the track"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "AlbumId",
|
name: "AlbumId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The ID of the album the track belongs to"
|
description: "The ID of the album the track belongs to"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "MediaTypeId",
|
name: "MediaTypeId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The ID of the media type the track is encoded with"
|
description: "The ID of the media type the track is encoded with"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "GenreId",
|
name: "GenreId",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The ID of the genre of the track"
|
description: "The ID of the genre of the track"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Composer",
|
name: "Composer",
|
||||||
type: ScalarType.String,
|
type: "string",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The name of the composer of the track"
|
description: "The name of the composer of the track"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Milliseconds",
|
name: "Milliseconds",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The length of the track in milliseconds"
|
description: "The length of the track in milliseconds"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Bytes",
|
name: "Bytes",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description: "The size of the track in bytes"
|
description: "The size of the track in bytes"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "UnitPrice",
|
name: "UnitPrice",
|
||||||
type: ScalarType.Number,
|
type: "number",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
description: "The price of the track"
|
description: "The price of the track"
|
||||||
},
|
},
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import Fastify from 'fastify';
|
import Fastify from 'fastify';
|
||||||
import FastifyCors from '@fastify/cors';
|
import FastifyCors from '@fastify/cors';
|
||||||
import { SchemaResponse } from './types/schema';
|
|
||||||
import { ProjectedRow, QueryRequest } from './types/query';
|
|
||||||
import { filterAvailableTables, getSchema, loadStaticData } from './data';
|
import { filterAvailableTables, getSchema, loadStaticData } from './data';
|
||||||
import { queryData } from './query';
|
import { queryData } from './query';
|
||||||
import { getConfig } from './config';
|
import { getConfig } from './config';
|
||||||
import { CapabilitiesResponse, capabilitiesResponse} from './capabilities';
|
import { capabilitiesResponse } from './capabilities';
|
||||||
|
import { CapabilitiesResponse, SchemaResponse, QueryRequest, QueryResponse } from './types';
|
||||||
|
|
||||||
const port = Number(process.env.PORT) || 8100;
|
const port = Number(process.env.PORT) || 8100;
|
||||||
const server = Fastify({ logger: { prettyPrint: true } });
|
const server = Fastify({ logger: { prettyPrint: true } });
|
||||||
@ -31,7 +30,7 @@ server.get<{ Reply: SchemaResponse }>("/schema", async (request, _response) => {
|
|||||||
return getSchema(config);
|
return getSchema(config);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.post<{ Body: QueryRequest, Reply: ProjectedRow[] }>("/query", async (request, _response) => {
|
server.post<{ Body: QueryRequest, Reply: QueryResponse }>("/query", async (request, _response) => {
|
||||||
server.log.info({ headers: request.headers, query: request.body, }, "query.request");
|
server.log.info({ headers: request.headers, query: request.body, }, "query.request");
|
||||||
const config = getConfig(request);
|
const config = getConfig(request);
|
||||||
const data = filterAvailableTables(staticData, config);
|
const data = filterAvailableTables(staticData, config);
|
||||||
|
@ -1,49 +1,56 @@
|
|||||||
import { Expression, Fields, BinaryComparisonOperator, OrderBy, OrderType, ProjectedRow, Query, QueryResponse, RelationshipType, ScalarValue, UnaryComparisonOperator, ComparisonValue, BinaryArrayComparisonOperator, QueryRequest, TableName, ComparisonColumn, TableRelationships, Relationship, RelationshipName } from "./types/query";
|
import { QueryRequest, TableRelationships, Relationship, Query, Field, OrderBy, Expression, BinaryComparisonOperator, UnaryComparisonOperator, BinaryArrayComparisonOperator, ComparisonColumn, ComparisonValue, ScalarValue, QueryResponse } from "./types";
|
||||||
import { coerceUndefinedToNull, crossProduct, unreachable, zip } from "./util";
|
import { coerceUndefinedToNull, crossProduct, unreachable, zip } from "./util";
|
||||||
|
|
||||||
type StaticData = {
|
type StaticData = {
|
||||||
[tableName: string]: Record<string, ScalarValue>[]
|
[tableName: string]: Record<string, ScalarValue>[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TableName = string
|
||||||
|
type RelationshipName = string
|
||||||
|
|
||||||
|
type ProjectedRow = {
|
||||||
|
[fieldName: string]: ScalarValue | ProjectedRow[] | ProjectedRow
|
||||||
|
}
|
||||||
|
|
||||||
const prettyPrintBinaryComparisonOperator = (operator: BinaryComparisonOperator): string => {
|
const prettyPrintBinaryComparisonOperator = (operator: BinaryComparisonOperator): string => {
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case BinaryComparisonOperator.GreaterThan: return ">";
|
case "greater_than": return ">";
|
||||||
case BinaryComparisonOperator.GreaterThanOrEqual: return ">=";
|
case "greater_than_or_equal": return ">=";
|
||||||
case BinaryComparisonOperator.LessThan: return "<";
|
case "less_than": return "<";
|
||||||
case BinaryComparisonOperator.LessThanOrEqual: return "<=";
|
case "less_than_or_equal": return "<=";
|
||||||
case BinaryComparisonOperator.Equal: return "==";
|
case "equal": return "==";
|
||||||
default: return unreachable(operator);
|
default: return unreachable(operator);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const prettyPrintBinaryArrayComparisonOperator = (operator: BinaryArrayComparisonOperator): string => {
|
const prettyPrintBinaryArrayComparisonOperator = (operator: BinaryArrayComparisonOperator): string => {
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case BinaryArrayComparisonOperator.In: return "IN";
|
case "in": return "IN";
|
||||||
default: return unreachable(operator);
|
default: return unreachable(operator);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const prettyPrintUnaryComparisonOperator = (operator: UnaryComparisonOperator): string => {
|
const prettyPrintUnaryComparisonOperator = (operator: UnaryComparisonOperator): string => {
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case UnaryComparisonOperator.IsNull: return "IS NULL";
|
case "is_null": return "IS NULL";
|
||||||
default: return unreachable(operator);
|
default: return unreachable(operator);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getBinaryComparisonOperatorEvaluator = (operator: BinaryComparisonOperator): ((left: ScalarValue, right: ScalarValue) => boolean) => {
|
const getBinaryComparisonOperatorEvaluator = (operator: BinaryComparisonOperator): ((left: ScalarValue, right: ScalarValue) => boolean) => {
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case BinaryComparisonOperator.GreaterThan: return (a, b) => a !== null && b !== null && a > b;
|
case "greater_than": return (a, b) => a !== null && b !== null && a > b;
|
||||||
case BinaryComparisonOperator.GreaterThanOrEqual: return (a, b) => a !== null && b !== null && a >= b;
|
case "greater_than_or_equal": return (a, b) => a !== null && b !== null && a >= b;
|
||||||
case BinaryComparisonOperator.LessThan: return (a, b) => a !== null && b !== null && a < b;
|
case "less_than": return (a, b) => a !== null && b !== null && a < b;
|
||||||
case BinaryComparisonOperator.LessThanOrEqual: return (a, b) => a !== null && b !== null && a <= b;
|
case "less_than_or_equal": return (a, b) => a !== null && b !== null && a <= b;
|
||||||
case BinaryComparisonOperator.Equal: return (a, b) => a !== null && b !== null && a === b;
|
case "equal": return (a, b) => a !== null && b !== null && a === b;
|
||||||
default: return unreachable(operator);
|
default: return unreachable(operator);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getBinaryArrayComparisonOperatorEvaluator = (operator: BinaryArrayComparisonOperator): ((left: ScalarValue, right: ScalarValue[]) => boolean) => {
|
const getBinaryArrayComparisonOperatorEvaluator = (operator: BinaryArrayComparisonOperator): ((left: ScalarValue, right: ScalarValue[]) => boolean) => {
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case BinaryArrayComparisonOperator.In: return (a, bs) => a !== null && bs.includes(a);
|
case "in": return (a, bs) => a !== null && bs.includes(a);
|
||||||
default: return unreachable(operator);
|
default: return unreachable(operator);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -51,7 +58,7 @@ const getBinaryArrayComparisonOperatorEvaluator = (operator: BinaryArrayComparis
|
|||||||
|
|
||||||
const getUnaryComparisonOperatorEvaluator = (operator: UnaryComparisonOperator): ((value: ScalarValue) => boolean) => {
|
const getUnaryComparisonOperatorEvaluator = (operator: UnaryComparisonOperator): ((value: ScalarValue) => boolean) => {
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case UnaryComparisonOperator.IsNull: return (v) => v === null;
|
case "is_null": return (v) => v === null;
|
||||||
default: return unreachable(operator);
|
default: return unreachable(operator);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -162,7 +169,7 @@ const sortRows = (rows: Record<string, ScalarValue>[], orderBy: OrderBy[]): Reco
|
|||||||
? -1
|
? -1
|
||||||
: 1;
|
: 1;
|
||||||
|
|
||||||
return ordering === OrderType.Descending ? -compared : compared;
|
return ordering === "desc" ? -compared : compared;
|
||||||
}, 0)
|
}, 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -191,7 +198,7 @@ const createFilterExpressionForRelationshipJoin = (row: Record<string, ScalarVal
|
|||||||
.map(([outerValue, innerColumnName]) => {
|
.map(([outerValue, innerColumnName]) => {
|
||||||
return {
|
return {
|
||||||
type: "binary_op",
|
type: "binary_op",
|
||||||
operator: BinaryComparisonOperator.Equal,
|
operator: "equal",
|
||||||
column: {
|
column: {
|
||||||
path: [],
|
path: [],
|
||||||
name: innerColumnName,
|
name: innerColumnName,
|
||||||
@ -222,7 +229,7 @@ const addRelationshipFilterToQuery = (row: Record<string, ScalarValue>, relation
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildFieldsForPathedComparisonColumn = (comparisonColumn: ComparisonColumn): Fields => {
|
const buildFieldsForPathedComparisonColumn = (comparisonColumn: ComparisonColumn): Record<string, Field> => {
|
||||||
const [relationshipName, ...remainingPath] = comparisonColumn.path;
|
const [relationshipName, ...remainingPath] = comparisonColumn.path;
|
||||||
if (relationshipName === undefined) {
|
if (relationshipName === undefined) {
|
||||||
return {
|
return {
|
||||||
@ -276,7 +283,7 @@ const makeGetComparisonColumnValues = (findRelationship: (relationshipName: Rela
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const projectRow = (fields: Fields, findRelationship: (relationshipName: RelationshipName) => Relationship, performQuery: (tableName: TableName, query: Query) => ProjectedRow[]) => (row: Record<string, ScalarValue>): ProjectedRow => {
|
const projectRow = (fields: Record<string, Field>, findRelationship: (relationshipName: RelationshipName) => Relationship, performQuery: (tableName: TableName, query: Query) => ProjectedRow[]) => (row: Record<string, ScalarValue>): ProjectedRow => {
|
||||||
const projectedRow: ProjectedRow = {};
|
const projectedRow: ProjectedRow = {};
|
||||||
for (const [fieldName, field] of Object.entries(fields)) {
|
for (const [fieldName, field] of Object.entries(fields)) {
|
||||||
|
|
||||||
@ -289,11 +296,11 @@ const projectRow = (fields: Fields, findRelationship: (relationshipName: Relatio
|
|||||||
const relationship = findRelationship(field.relationship);
|
const relationship = findRelationship(field.relationship);
|
||||||
const subquery = addRelationshipFilterToQuery(row, relationship, field.query);
|
const subquery = addRelationshipFilterToQuery(row, relationship, field.query);
|
||||||
switch (relationship.relationship_type) {
|
switch (relationship.relationship_type) {
|
||||||
case RelationshipType.Object:
|
case "object":
|
||||||
projectedRow[fieldName] = subquery ? coerceUndefinedToNull(performQuery(relationship.target_table, subquery)[0]) : null;
|
projectedRow[fieldName] = subquery ? coerceUndefinedToNull(performQuery(relationship.target_table, subquery)[0]) : null;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RelationshipType.Array:
|
case "array":
|
||||||
projectedRow[fieldName] = subquery ? performQuery(relationship.target_table, subquery) : [];
|
projectedRow[fieldName] = subquery ? performQuery(relationship.target_table, subquery) : [];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
1022
dc-agents/reference/src/types/agent.openapi.json
Normal file
1022
dc-agents/reference/src/types/agent.openapi.json
Normal file
File diff suppressed because it is too large
Load Diff
49
dc-agents/reference/src/types/index.ts
Normal file
49
dc-agents/reference/src/types/index.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type { AndExpression } from './models/AndExpression';
|
||||||
|
export type { AnotherColumnComparison } from './models/AnotherColumnComparison';
|
||||||
|
export type { ApplyBinaryArrayComparisonExpression } from './models/ApplyBinaryArrayComparisonExpression';
|
||||||
|
export type { ApplyBinaryComparisonOperator } from './models/ApplyBinaryComparisonOperator';
|
||||||
|
export type { ApplyUnaryComparisonOperator } from './models/ApplyUnaryComparisonOperator';
|
||||||
|
export type { BinaryArrayComparisonOperator } from './models/BinaryArrayComparisonOperator';
|
||||||
|
export type { BinaryComparisonOperator } from './models/BinaryComparisonOperator';
|
||||||
|
export type { BooleanOperators } from './models/BooleanOperators';
|
||||||
|
export type { Capabilities } from './models/Capabilities';
|
||||||
|
export type { CapabilitiesResponse } from './models/CapabilitiesResponse';
|
||||||
|
export type { ColumnField } from './models/ColumnField';
|
||||||
|
export type { ColumnInfo } from './models/ColumnInfo';
|
||||||
|
export type { ComparisonColumn } from './models/ComparisonColumn';
|
||||||
|
export type { ComparisonOperators } from './models/ComparisonOperators';
|
||||||
|
export type { ComparisonValue } from './models/ComparisonValue';
|
||||||
|
export type { ConfigSchemaResponse } from './models/ConfigSchemaResponse';
|
||||||
|
export type { Expression } from './models/Expression';
|
||||||
|
export type { Field } from './models/Field';
|
||||||
|
export type { FilteringCapabilities } from './models/FilteringCapabilities';
|
||||||
|
export type { MutationCapabilities } from './models/MutationCapabilities';
|
||||||
|
export type { NotExpression } from './models/NotExpression';
|
||||||
|
export type { OpenApiDiscriminator } from './models/OpenApiDiscriminator';
|
||||||
|
export type { OpenApiExternalDocumentation } from './models/OpenApiExternalDocumentation';
|
||||||
|
export type { OpenApiReference } from './models/OpenApiReference';
|
||||||
|
export type { OpenApiSchema } from './models/OpenApiSchema';
|
||||||
|
export type { OpenApiXml } from './models/OpenApiXml';
|
||||||
|
export type { OrderBy } from './models/OrderBy';
|
||||||
|
export type { OrderType } from './models/OrderType';
|
||||||
|
export type { OrExpression } from './models/OrExpression';
|
||||||
|
export type { Query } from './models/Query';
|
||||||
|
export type { QueryCapabilities } from './models/QueryCapabilities';
|
||||||
|
export type { QueryRequest } from './models/QueryRequest';
|
||||||
|
export type { QueryResponse } from './models/QueryResponse';
|
||||||
|
export type { Relationship } from './models/Relationship';
|
||||||
|
export type { RelationshipCapabilities } from './models/RelationshipCapabilities';
|
||||||
|
export type { RelationshipField } from './models/RelationshipField';
|
||||||
|
export type { RelationshipType } from './models/RelationshipType';
|
||||||
|
export type { ScalarType } from './models/ScalarType';
|
||||||
|
export type { ScalarValue } from './models/ScalarValue';
|
||||||
|
export type { ScalarValueComparison } from './models/ScalarValueComparison';
|
||||||
|
export type { SchemaResponse } from './models/SchemaResponse';
|
||||||
|
export type { SubscriptionCapabilities } from './models/SubscriptionCapabilities';
|
||||||
|
export type { TableInfo } from './models/TableInfo';
|
||||||
|
export type { TableRelationships } from './models/TableRelationships';
|
||||||
|
export type { UnaryComparisonOperator } from './models/UnaryComparisonOperator';
|
11
dc-agents/reference/src/types/models/AndExpression.ts
Normal file
11
dc-agents/reference/src/types/models/AndExpression.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { Expression } from './Expression';
|
||||||
|
|
||||||
|
export type AndExpression = {
|
||||||
|
expressions: Array<Expression>;
|
||||||
|
type: 'and';
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { ComparisonColumn } from './ComparisonColumn';
|
||||||
|
|
||||||
|
export type AnotherColumnComparison = {
|
||||||
|
column: ComparisonColumn;
|
||||||
|
type: 'column';
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,15 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { BinaryArrayComparisonOperator } from './BinaryArrayComparisonOperator';
|
||||||
|
import type { ComparisonColumn } from './ComparisonColumn';
|
||||||
|
import type { ScalarValue } from './ScalarValue';
|
||||||
|
|
||||||
|
export type ApplyBinaryArrayComparisonExpression = {
|
||||||
|
column: ComparisonColumn;
|
||||||
|
operator: BinaryArrayComparisonOperator;
|
||||||
|
type: 'binary_arr_op';
|
||||||
|
values: Array<ScalarValue>;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,15 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { BinaryComparisonOperator } from './BinaryComparisonOperator';
|
||||||
|
import type { ComparisonColumn } from './ComparisonColumn';
|
||||||
|
import type { ComparisonValue } from './ComparisonValue';
|
||||||
|
|
||||||
|
export type ApplyBinaryComparisonOperator = {
|
||||||
|
column: ComparisonColumn;
|
||||||
|
operator: BinaryComparisonOperator;
|
||||||
|
type: 'binary_op';
|
||||||
|
value: ComparisonValue;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { ComparisonColumn } from './ComparisonColumn';
|
||||||
|
import type { UnaryComparisonOperator } from './UnaryComparisonOperator';
|
||||||
|
|
||||||
|
export type ApplyUnaryComparisonOperator = {
|
||||||
|
column: ComparisonColumn;
|
||||||
|
operator: UnaryComparisonOperator;
|
||||||
|
type: 'unary_op';
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type BinaryArrayComparisonOperator = 'in';
|
@ -0,0 +1,5 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type BinaryComparisonOperator = 'less_than' | 'less_than_or_equal' | 'greater_than' | 'greater_than_or_equal' | 'equal';
|
7
dc-agents/reference/src/types/models/BooleanOperators.ts
Normal file
7
dc-agents/reference/src/types/models/BooleanOperators.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type BooleanOperators = {
|
||||||
|
};
|
||||||
|
|
18
dc-agents/reference/src/types/models/Capabilities.ts
Normal file
18
dc-agents/reference/src/types/models/Capabilities.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { FilteringCapabilities } from './FilteringCapabilities';
|
||||||
|
import type { MutationCapabilities } from './MutationCapabilities';
|
||||||
|
import type { QueryCapabilities } from './QueryCapabilities';
|
||||||
|
import type { RelationshipCapabilities } from './RelationshipCapabilities';
|
||||||
|
import type { SubscriptionCapabilities } from './SubscriptionCapabilities';
|
||||||
|
|
||||||
|
export type Capabilities = {
|
||||||
|
filtering?: FilteringCapabilities;
|
||||||
|
mutations?: MutationCapabilities;
|
||||||
|
queries?: QueryCapabilities;
|
||||||
|
relationships?: RelationshipCapabilities;
|
||||||
|
subscriptions?: SubscriptionCapabilities;
|
||||||
|
};
|
||||||
|
|
12
dc-agents/reference/src/types/models/CapabilitiesResponse.ts
Normal file
12
dc-agents/reference/src/types/models/CapabilitiesResponse.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { Capabilities } from './Capabilities';
|
||||||
|
import type { ConfigSchemaResponse } from './ConfigSchemaResponse';
|
||||||
|
|
||||||
|
export type CapabilitiesResponse = {
|
||||||
|
capabilities: Capabilities;
|
||||||
|
configSchemas: ConfigSchemaResponse;
|
||||||
|
};
|
||||||
|
|
9
dc-agents/reference/src/types/models/ColumnField.ts
Normal file
9
dc-agents/reference/src/types/models/ColumnField.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type ColumnField = {
|
||||||
|
column: string;
|
||||||
|
type: 'column';
|
||||||
|
};
|
||||||
|
|
22
dc-agents/reference/src/types/models/ColumnInfo.ts
Normal file
22
dc-agents/reference/src/types/models/ColumnInfo.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { ScalarType } from './ScalarType';
|
||||||
|
|
||||||
|
export type ColumnInfo = {
|
||||||
|
/**
|
||||||
|
* Column description
|
||||||
|
*/
|
||||||
|
description?: string | null;
|
||||||
|
/**
|
||||||
|
* Column name
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* Is column nullable
|
||||||
|
*/
|
||||||
|
nullable: boolean;
|
||||||
|
type: ScalarType;
|
||||||
|
};
|
||||||
|
|
15
dc-agents/reference/src/types/models/ComparisonColumn.ts
Normal file
15
dc-agents/reference/src/types/models/ComparisonColumn.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type ComparisonColumn = {
|
||||||
|
/**
|
||||||
|
* The name of the column
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* The relationship path from the current query table to the table that contains the specified column. Empty array means the current query table.
|
||||||
|
*/
|
||||||
|
path: Array<string>;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,7 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type ComparisonOperators = {
|
||||||
|
};
|
||||||
|
|
9
dc-agents/reference/src/types/models/ComparisonValue.ts
Normal file
9
dc-agents/reference/src/types/models/ComparisonValue.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { AnotherColumnComparison } from './AnotherColumnComparison';
|
||||||
|
import type { ScalarValueComparison } from './ScalarValueComparison';
|
||||||
|
|
||||||
|
export type ComparisonValue = (AnotherColumnComparison | ScalarValueComparison);
|
||||||
|
|
11
dc-agents/reference/src/types/models/ConfigSchemaResponse.ts
Normal file
11
dc-agents/reference/src/types/models/ConfigSchemaResponse.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { OpenApiSchema } from './OpenApiSchema';
|
||||||
|
|
||||||
|
export type ConfigSchemaResponse = {
|
||||||
|
configSchema: OpenApiSchema;
|
||||||
|
otherSchemas: Record<string, OpenApiSchema>;
|
||||||
|
};
|
||||||
|
|
13
dc-agents/reference/src/types/models/Expression.ts
Normal file
13
dc-agents/reference/src/types/models/Expression.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { AndExpression } from './AndExpression';
|
||||||
|
import type { ApplyBinaryArrayComparisonExpression } from './ApplyBinaryArrayComparisonExpression';
|
||||||
|
import type { ApplyBinaryComparisonOperator } from './ApplyBinaryComparisonOperator';
|
||||||
|
import type { ApplyUnaryComparisonOperator } from './ApplyUnaryComparisonOperator';
|
||||||
|
import type { NotExpression } from './NotExpression';
|
||||||
|
import type { OrExpression } from './OrExpression';
|
||||||
|
|
||||||
|
export type Expression = (AndExpression | OrExpression | NotExpression | ApplyBinaryComparisonOperator | ApplyBinaryArrayComparisonExpression | ApplyUnaryComparisonOperator);
|
||||||
|
|
9
dc-agents/reference/src/types/models/Field.ts
Normal file
9
dc-agents/reference/src/types/models/Field.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { ColumnField } from './ColumnField';
|
||||||
|
import type { RelationshipField } from './RelationshipField';
|
||||||
|
|
||||||
|
export type Field = (ColumnField | RelationshipField);
|
||||||
|
|
@ -0,0 +1,12 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { BooleanOperators } from './BooleanOperators';
|
||||||
|
import type { ComparisonOperators } from './ComparisonOperators';
|
||||||
|
|
||||||
|
export type FilteringCapabilities = {
|
||||||
|
booleanOperators: BooleanOperators;
|
||||||
|
comparisonOperators: ComparisonOperators;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,7 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type MutationCapabilities = {
|
||||||
|
};
|
||||||
|
|
11
dc-agents/reference/src/types/models/NotExpression.ts
Normal file
11
dc-agents/reference/src/types/models/NotExpression.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { Expression } from './Expression';
|
||||||
|
|
||||||
|
export type NotExpression = {
|
||||||
|
expression: Expression;
|
||||||
|
type: 'not';
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type OpenApiDiscriminator = {
|
||||||
|
mapping?: Record<string, string>;
|
||||||
|
propertyName: string;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type OpenApiExternalDocumentation = {
|
||||||
|
description?: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
8
dc-agents/reference/src/types/models/OpenApiReference.ts
Normal file
8
dc-agents/reference/src/types/models/OpenApiReference.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type OpenApiReference = {
|
||||||
|
$ref: string;
|
||||||
|
};
|
||||||
|
|
47
dc-agents/reference/src/types/models/OpenApiSchema.ts
Normal file
47
dc-agents/reference/src/types/models/OpenApiSchema.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { OpenApiDiscriminator } from './OpenApiDiscriminator';
|
||||||
|
import type { OpenApiExternalDocumentation } from './OpenApiExternalDocumentation';
|
||||||
|
import type { OpenApiReference } from './OpenApiReference';
|
||||||
|
import type { OpenApiXml } from './OpenApiXml';
|
||||||
|
|
||||||
|
export type OpenApiSchema = {
|
||||||
|
additionalProperties?: any;
|
||||||
|
allOf?: Array<(OpenApiSchema | OpenApiReference)>;
|
||||||
|
anyOf?: Array<(OpenApiSchema | OpenApiReference)>;
|
||||||
|
default?: any;
|
||||||
|
deprecated?: boolean;
|
||||||
|
description?: string;
|
||||||
|
discriminator?: OpenApiDiscriminator;
|
||||||
|
enum?: Array<any>;
|
||||||
|
example?: any;
|
||||||
|
exclusiveMaximum?: boolean;
|
||||||
|
exclusiveMinimum?: boolean;
|
||||||
|
externalDocs?: OpenApiExternalDocumentation;
|
||||||
|
format?: string;
|
||||||
|
items?: (OpenApiSchema | OpenApiReference);
|
||||||
|
maxItems?: number;
|
||||||
|
maxLength?: number;
|
||||||
|
maxProperties?: number;
|
||||||
|
maximum?: number;
|
||||||
|
minItems?: number;
|
||||||
|
minLength?: number;
|
||||||
|
minProperties?: number;
|
||||||
|
minimum?: number;
|
||||||
|
multipleOf?: number;
|
||||||
|
not?: (OpenApiSchema | OpenApiReference);
|
||||||
|
nullable?: boolean;
|
||||||
|
oneOf?: Array<(OpenApiSchema | OpenApiReference)>;
|
||||||
|
pattern?: string;
|
||||||
|
properties?: Record<string, (OpenApiSchema | OpenApiReference)>;
|
||||||
|
readOnly?: boolean;
|
||||||
|
required?: Array<string>;
|
||||||
|
title?: string;
|
||||||
|
type?: 'array' | 'boolean' | 'integer' | 'number' | 'object' | 'string';
|
||||||
|
uniqueItems?: boolean;
|
||||||
|
writeOnly?: boolean;
|
||||||
|
xml?: OpenApiXml;
|
||||||
|
};
|
||||||
|
|
12
dc-agents/reference/src/types/models/OpenApiXml.ts
Normal file
12
dc-agents/reference/src/types/models/OpenApiXml.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type OpenApiXml = {
|
||||||
|
attribute?: boolean;
|
||||||
|
name?: string;
|
||||||
|
namespace?: string;
|
||||||
|
prefix?: string;
|
||||||
|
wrapped?: boolean;
|
||||||
|
};
|
||||||
|
|
11
dc-agents/reference/src/types/models/OrExpression.ts
Normal file
11
dc-agents/reference/src/types/models/OrExpression.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { Expression } from './Expression';
|
||||||
|
|
||||||
|
export type OrExpression = {
|
||||||
|
expressions: Array<Expression>;
|
||||||
|
type: 'or';
|
||||||
|
};
|
||||||
|
|
14
dc-agents/reference/src/types/models/OrderBy.ts
Normal file
14
dc-agents/reference/src/types/models/OrderBy.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { OrderType } from './OrderType';
|
||||||
|
|
||||||
|
export type OrderBy = {
|
||||||
|
/**
|
||||||
|
* Column to order by
|
||||||
|
*/
|
||||||
|
column: string;
|
||||||
|
ordering: OrderType;
|
||||||
|
};
|
||||||
|
|
5
dc-agents/reference/src/types/models/OrderType.ts
Normal file
5
dc-agents/reference/src/types/models/OrderType.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type OrderType = 'asc' | 'desc';
|
28
dc-agents/reference/src/types/models/Query.ts
Normal file
28
dc-agents/reference/src/types/models/Query.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { Expression } from './Expression';
|
||||||
|
import type { Field } from './Field';
|
||||||
|
import type { OrderBy } from './OrderBy';
|
||||||
|
|
||||||
|
export type Query = {
|
||||||
|
/**
|
||||||
|
* Fields of the query
|
||||||
|
*/
|
||||||
|
fields: Record<string, Field>;
|
||||||
|
/**
|
||||||
|
* Optionally limit to N results
|
||||||
|
*/
|
||||||
|
limit?: number | null;
|
||||||
|
/**
|
||||||
|
* Optionally offset from the Nth result
|
||||||
|
*/
|
||||||
|
offset?: number | null;
|
||||||
|
/**
|
||||||
|
* Optionally order the results by the value of one or more fields
|
||||||
|
*/
|
||||||
|
order_by?: Array<OrderBy> | null;
|
||||||
|
where?: Expression;
|
||||||
|
};
|
||||||
|
|
11
dc-agents/reference/src/types/models/QueryCapabilities.ts
Normal file
11
dc-agents/reference/src/types/models/QueryCapabilities.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type QueryCapabilities = {
|
||||||
|
/**
|
||||||
|
* Does the agent support querying a table by primary key?
|
||||||
|
*/
|
||||||
|
supportsPrimaryKeys: boolean;
|
||||||
|
};
|
||||||
|
|
19
dc-agents/reference/src/types/models/QueryRequest.ts
Normal file
19
dc-agents/reference/src/types/models/QueryRequest.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { Query } from './Query';
|
||||||
|
import type { TableRelationships } from './TableRelationships';
|
||||||
|
|
||||||
|
export type QueryRequest = {
|
||||||
|
query: Query;
|
||||||
|
/**
|
||||||
|
* The name of the table to query
|
||||||
|
*/
|
||||||
|
table: string;
|
||||||
|
/**
|
||||||
|
* The relationships between tables involved in the entire query request
|
||||||
|
*/
|
||||||
|
table_relationships: Array<TableRelationships>;
|
||||||
|
};
|
||||||
|
|
5
dc-agents/reference/src/types/models/QueryResponse.ts
Normal file
5
dc-agents/reference/src/types/models/QueryResponse.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type QueryResponse = Array<Record<string, any>>;
|
18
dc-agents/reference/src/types/models/Relationship.ts
Normal file
18
dc-agents/reference/src/types/models/Relationship.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { RelationshipType } from './RelationshipType';
|
||||||
|
|
||||||
|
export type Relationship = {
|
||||||
|
/**
|
||||||
|
* A mapping between columns on the source table to columns on the target table
|
||||||
|
*/
|
||||||
|
column_mapping: Record<string, string>;
|
||||||
|
relationship_type: RelationshipType;
|
||||||
|
/**
|
||||||
|
* The name of the target table in the relationship
|
||||||
|
*/
|
||||||
|
target_table: string;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,7 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type RelationshipCapabilities = {
|
||||||
|
};
|
||||||
|
|
15
dc-agents/reference/src/types/models/RelationshipField.ts
Normal file
15
dc-agents/reference/src/types/models/RelationshipField.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { Query } from './Query';
|
||||||
|
|
||||||
|
export type RelationshipField = {
|
||||||
|
query: Query;
|
||||||
|
/**
|
||||||
|
* The name of the relationship to follow for the subquery
|
||||||
|
*/
|
||||||
|
relationship: string;
|
||||||
|
type: 'relationship';
|
||||||
|
};
|
||||||
|
|
5
dc-agents/reference/src/types/models/RelationshipType.ts
Normal file
5
dc-agents/reference/src/types/models/RelationshipType.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type RelationshipType = 'object' | 'array';
|
5
dc-agents/reference/src/types/models/ScalarType.ts
Normal file
5
dc-agents/reference/src/types/models/ScalarType.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type ScalarType = 'string' | 'number' | 'bool';
|
6
dc-agents/reference/src/types/models/ScalarValue.ts
Normal file
6
dc-agents/reference/src/types/models/ScalarValue.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type ScalarValue = (string | number | boolean | null);
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { ScalarValue } from './ScalarValue';
|
||||||
|
|
||||||
|
export type ScalarValueComparison = {
|
||||||
|
type: 'scalar';
|
||||||
|
value: ScalarValue;
|
||||||
|
};
|
||||||
|
|
13
dc-agents/reference/src/types/models/SchemaResponse.ts
Normal file
13
dc-agents/reference/src/types/models/SchemaResponse.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { TableInfo } from './TableInfo';
|
||||||
|
|
||||||
|
export type SchemaResponse = {
|
||||||
|
/**
|
||||||
|
* Available tables
|
||||||
|
*/
|
||||||
|
tables: Array<TableInfo>;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,7 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type SubscriptionCapabilities = {
|
||||||
|
};
|
||||||
|
|
25
dc-agents/reference/src/types/models/TableInfo.ts
Normal file
25
dc-agents/reference/src/types/models/TableInfo.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { ColumnInfo } from './ColumnInfo';
|
||||||
|
|
||||||
|
export type TableInfo = {
|
||||||
|
/**
|
||||||
|
* The columns of the table
|
||||||
|
*/
|
||||||
|
columns: Array<ColumnInfo>;
|
||||||
|
/**
|
||||||
|
* Description of the table
|
||||||
|
*/
|
||||||
|
description?: string | null;
|
||||||
|
/**
|
||||||
|
* The name of the table
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* The primary key of the table
|
||||||
|
*/
|
||||||
|
primary_key?: string | null;
|
||||||
|
};
|
||||||
|
|
17
dc-agents/reference/src/types/models/TableRelationships.ts
Normal file
17
dc-agents/reference/src/types/models/TableRelationships.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import type { Relationship } from './Relationship';
|
||||||
|
|
||||||
|
export type TableRelationships = {
|
||||||
|
/**
|
||||||
|
* A map of relationships from the source table to target tables. The key of the map is the relationship name
|
||||||
|
*/
|
||||||
|
relationships: Record<string, Relationship>;
|
||||||
|
/**
|
||||||
|
* The name of the source table in the relationship
|
||||||
|
*/
|
||||||
|
source_table: string;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export type UnaryComparisonOperator = 'is_null';
|
@ -1,148 +0,0 @@
|
|||||||
export type QueryRequest = {
|
|
||||||
table: TableName,
|
|
||||||
table_relationships: TableRelationships[],
|
|
||||||
query: Query,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TableName = string
|
|
||||||
|
|
||||||
export type TableRelationships = {
|
|
||||||
source_table: TableName,
|
|
||||||
relationships: { [relationshipName: RelationshipName]: Relationship }
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Relationship = {
|
|
||||||
target_table: TableName,
|
|
||||||
relationship_type: RelationshipType,
|
|
||||||
column_mapping: { [source: SourceColumnName]: TargetColumnName },
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SourceColumnName = ColumnName
|
|
||||||
export type TargetColumnName = ColumnName
|
|
||||||
|
|
||||||
export type RelationshipName = string
|
|
||||||
|
|
||||||
export enum RelationshipType {
|
|
||||||
Object = "object",
|
|
||||||
Array = "array"
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Query = {
|
|
||||||
fields: Fields,
|
|
||||||
limit?: number | null,
|
|
||||||
offset?: number | null,
|
|
||||||
where?: Expression | null,
|
|
||||||
order_by?: OrderBy[],
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Fields = { [fieldName: string]: Field }
|
|
||||||
|
|
||||||
export type Field = ColumnField | RelationshipField
|
|
||||||
|
|
||||||
export type ColumnName = string
|
|
||||||
export type ColumnField = {
|
|
||||||
type: "column",
|
|
||||||
column: ColumnName,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RelationshipField = {
|
|
||||||
type: "relationship",
|
|
||||||
relationship: RelationshipName
|
|
||||||
query: Query,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ScalarValue = string | number | boolean | null
|
|
||||||
|
|
||||||
export type ComparisonColumn = {
|
|
||||||
path: RelationshipName[],
|
|
||||||
name: ColumnName,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ComparisonValue =
|
|
||||||
| AnotherColumnComparisonValue
|
|
||||||
| ScalarComparisonValue
|
|
||||||
|
|
||||||
export type AnotherColumnComparisonValue = {
|
|
||||||
type: "column",
|
|
||||||
column: ComparisonColumn,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ScalarComparisonValue = {
|
|
||||||
type: "scalar",
|
|
||||||
value: ScalarValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Expression =
|
|
||||||
| AndExpression
|
|
||||||
| OrExpression
|
|
||||||
| NotExpression
|
|
||||||
| ApplyBinaryComparisonOperatorExpression
|
|
||||||
| ApplyBinaryArrayComparisonOperatorExpression
|
|
||||||
| ApplyUnaryComparisonOperatorExpression
|
|
||||||
|
|
||||||
export type AndExpression = {
|
|
||||||
type: "and",
|
|
||||||
expressions: Expression[],
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OrExpression = {
|
|
||||||
type: "or",
|
|
||||||
expressions: Expression[],
|
|
||||||
}
|
|
||||||
|
|
||||||
export type NotExpression = {
|
|
||||||
type: "not",
|
|
||||||
expression: Expression,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ApplyBinaryComparisonOperatorExpression = {
|
|
||||||
type: "binary_op",
|
|
||||||
operator: BinaryComparisonOperator,
|
|
||||||
column: ComparisonColumn,
|
|
||||||
value: ComparisonValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ApplyBinaryArrayComparisonOperatorExpression = {
|
|
||||||
type: "binary_arr_op",
|
|
||||||
operator: BinaryArrayComparisonOperator,
|
|
||||||
column: ComparisonColumn,
|
|
||||||
values: ScalarValue[],
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ApplyUnaryComparisonOperatorExpression = {
|
|
||||||
type: "unary_op",
|
|
||||||
operator: UnaryComparisonOperator,
|
|
||||||
column: ComparisonColumn,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum BinaryComparisonOperator {
|
|
||||||
LessThan = "less_than",
|
|
||||||
LessThanOrEqual = "less_than_or_equal",
|
|
||||||
GreaterThan = "greater_than",
|
|
||||||
GreaterThanOrEqual = "greater_than_or_equal",
|
|
||||||
Equal = "equal",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum BinaryArrayComparisonOperator {
|
|
||||||
In = "in",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum UnaryComparisonOperator {
|
|
||||||
IsNull = "is_null",
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OrderBy = {
|
|
||||||
column: ColumnName,
|
|
||||||
ordering: OrderType,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum OrderType {
|
|
||||||
Ascending = "asc",
|
|
||||||
Descending = "desc",
|
|
||||||
}
|
|
||||||
|
|
||||||
export type QueryResponse = ProjectedRow[]
|
|
||||||
|
|
||||||
export type ProjectedRow = {
|
|
||||||
[fieldName: string]: ScalarValue | ProjectedRow[] | ProjectedRow
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
export type SchemaResponse = {
|
|
||||||
tables: Table[],
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Table = {
|
|
||||||
name: string,
|
|
||||||
columns: ColumnInfo[],
|
|
||||||
primary_key?: string | null,
|
|
||||||
description?: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ColumnInfo = {
|
|
||||||
name: string,
|
|
||||||
type: ScalarType,
|
|
||||||
nullable: boolean,
|
|
||||||
description?: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ScalarType {
|
|
||||||
String = "string",
|
|
||||||
Number = "number",
|
|
||||||
Boolean = "bool"
|
|
||||||
}
|
|
@ -1,9 +1,8 @@
|
|||||||
export const coerceUndefinedToNull = <T>(v: T | undefined): T | null => v === undefined ? null : v;
|
export const coerceUndefinedToNull = <T>(v: T | undefined): T | null => v === undefined ? null : v;
|
||||||
|
|
||||||
export const unreachable = (x: never): never => { throw new Error(`Unreachable code reached! The types lied! 😭 Unexpected value: ${x}`) };
|
export const unreachable = (x: never): never => { throw new Error(`Unreachable code reached! The types lied! 😭 Unexpected value: ${x}`) };
|
||||||
;
|
|
||||||
|
|
||||||
export const zip = <T, U>(arr1: T[], arr2: U[]): [T,U][] => {
|
export const zip = <T, U>(arr1: T[], arr2: U[]): [T, U][] => {
|
||||||
const length = Math.min(arr1.length, arr2.length);
|
const length = Math.min(arr1.length, arr2.length);
|
||||||
const newArray = Array(length);
|
const newArray = Array(length);
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
@ -12,6 +11,6 @@ export const zip = <T, U>(arr1: T[], arr2: U[]): [T,U][] => {
|
|||||||
return newArray;
|
return newArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const crossProduct = <T, U>(arr1: T[], arr2: U[]): [T,U][] => {
|
export const crossProduct = <T, U>(arr1: T[], arr2: U[]): [T, U][] => {
|
||||||
return arr1.flatMap(a1 => arr2.map(a2 => [a1, a2]) as [T,U][]);
|
return arr1.flatMap(a1 => arr2.map(a2 => [a1, a2]) as [T, U][]);
|
||||||
};
|
};
|
||||||
|
@ -7,13 +7,12 @@ module Hasura.Backends.DataConnector.API
|
|||||||
ConfigHeader,
|
ConfigHeader,
|
||||||
SourceNameHeader,
|
SourceNameHeader,
|
||||||
SourceName,
|
SourceName,
|
||||||
openApiSchemaJson,
|
openApiSchema,
|
||||||
Routes (..),
|
Routes (..),
|
||||||
apiClient,
|
apiClient,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
import Data.Aeson qualified as J
|
|
||||||
import Data.Data (Proxy (..))
|
import Data.Data (Proxy (..))
|
||||||
import Data.OpenApi (OpenApi)
|
import Data.OpenApi (OpenApi)
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
@ -22,7 +21,6 @@ import Servant.API
|
|||||||
import Servant.API.Generic
|
import Servant.API.Generic
|
||||||
import Servant.Client (Client, ClientM, client)
|
import Servant.Client (Client, ClientM, client)
|
||||||
import Servant.OpenApi
|
import Servant.OpenApi
|
||||||
import Prelude
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Servant Routes
|
-- Servant Routes
|
||||||
@ -68,13 +66,6 @@ type Api = CapabilitiesApi :<|> SchemaApi :<|> QueryApi
|
|||||||
openApiSchema :: OpenApi
|
openApiSchema :: OpenApi
|
||||||
openApiSchema = toOpenApi (Proxy @Api)
|
openApiSchema = toOpenApi (Proxy @Api)
|
||||||
|
|
||||||
-- | The OpenAPI 3.0 schema for the API
|
|
||||||
--
|
|
||||||
-- This is not exposed as the 'OpenApi' type because we need to do some hackery in
|
|
||||||
-- the serialized JSON to work around some limitations in the openapi3 library
|
|
||||||
openApiSchemaJson :: J.Value
|
|
||||||
openApiSchemaJson = V0.fixExternalSchemaRefsInComponentSchemas $ J.toJSON openApiSchema
|
|
||||||
|
|
||||||
apiClient :: Client ClientM (NamedRoutes Routes)
|
apiClient :: Client ClientM (NamedRoutes Routes)
|
||||||
apiClient =
|
apiClient =
|
||||||
client (Proxy @(NamedRoutes Routes))
|
client (Proxy @(NamedRoutes Routes))
|
||||||
|
@ -22,7 +22,7 @@ import Data.Aeson (FromJSON, ToJSON)
|
|||||||
import Data.Data (Data, Proxy (..))
|
import Data.Data (Data, Proxy (..))
|
||||||
import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
|
import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
|
||||||
import Data.Hashable (Hashable)
|
import Data.Hashable (Hashable)
|
||||||
import Data.OpenApi (NamedSchema (..), OpenApiType (OpenApiObject), Referenced (..), Schema (..), ToSchema (..))
|
import Data.OpenApi (NamedSchema (..), OpenApiType (OpenApiObject), Schema (..), ToSchema (..), declareSchemaRef)
|
||||||
import GHC.Generics (Generic)
|
import GHC.Generics (Generic)
|
||||||
import Hasura.Backends.DataConnector.API.V0.ConfigSchema (ConfigSchemaResponse)
|
import Hasura.Backends.DataConnector.API.V0.ConfigSchema (ConfigSchemaResponse)
|
||||||
import Prelude
|
import Prelude
|
||||||
@ -137,8 +137,8 @@ instance HasCodec CapabilitiesResponse where
|
|||||||
|
|
||||||
instance ToSchema CapabilitiesResponse where
|
instance ToSchema CapabilitiesResponse where
|
||||||
declareNamedSchema _ = do
|
declareNamedSchema _ = do
|
||||||
capabilitiesSchema <- declareNamedSchema (Proxy @Capabilities)
|
capabilitiesSchemaRef <- declareSchemaRef (Proxy @Capabilities)
|
||||||
configSchemasSchema <- declareNamedSchema (Proxy @ConfigSchemaResponse)
|
configSchemasSchemaRef <- declareSchemaRef (Proxy @ConfigSchemaResponse)
|
||||||
let schema =
|
let schema =
|
||||||
mempty
|
mempty
|
||||||
{ _schemaType = Just OpenApiObject,
|
{ _schemaType = Just OpenApiObject,
|
||||||
@ -146,8 +146,8 @@ instance ToSchema CapabilitiesResponse where
|
|||||||
_schemaRequired = ["capabilities", "configSchemas"],
|
_schemaRequired = ["capabilities", "configSchemas"],
|
||||||
_schemaProperties =
|
_schemaProperties =
|
||||||
InsOrdHashMap.fromList
|
InsOrdHashMap.fromList
|
||||||
[ ("capabilities", Inline $ _namedSchemaSchema capabilitiesSchema),
|
[ ("capabilities", capabilitiesSchemaRef),
|
||||||
("configSchemas", Inline $ _namedSchemaSchema configSchemasSchema)
|
("configSchemas", configSchemasSchemaRef)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,6 @@ module Hasura.Backends.DataConnector.API.V0.ConfigSchema
|
|||||||
( Config (..),
|
( Config (..),
|
||||||
ConfigSchemaResponse (..),
|
ConfigSchemaResponse (..),
|
||||||
validateConfigAgainstConfigSchema,
|
validateConfigAgainstConfigSchema,
|
||||||
fixExternalSchemaRefsInComponentSchemas,
|
|
||||||
fixExternalSchemaRefsInSchema,
|
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
@ -20,8 +18,9 @@ import Data.ByteString.Lazy qualified as BSL
|
|||||||
import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
|
import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
|
||||||
import Data.Hashable (Hashable)
|
import Data.Hashable (Hashable)
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
import Data.OpenApi (AdditionalProperties (..), Definitions, NamedSchema (..), OpenApiType (..), Reference (..), Referenced (..), Schema (..), ToParamSchema (..), ToSchema (..), ValidationError)
|
import Data.OpenApi (AdditionalProperties (..), Definitions, NamedSchema (..), OpenApiItems (..), OpenApiType (..), Reference (..), Referenced (..), Schema (..), ToParamSchema (..), ToSchema (..), ValidationError)
|
||||||
import Data.OpenApi qualified as OpenApi
|
import Data.OpenApi qualified as OpenApi
|
||||||
|
import Data.OpenApi.Declare (Declare, MonadDeclare (..))
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Data.Text qualified as Text
|
import Data.Text qualified as Text
|
||||||
import Data.Text.Encoding qualified as Text
|
import Data.Text.Encoding qualified as Text
|
||||||
@ -75,33 +74,184 @@ instance Autodocodec.HasCodec ConfigSchemaResponse where
|
|||||||
codec = Autodocodec.codecViaAeson "Configuration schemas"
|
codec = Autodocodec.codecViaAeson "Configuration schemas"
|
||||||
|
|
||||||
instance ToSchema ConfigSchemaResponse where
|
instance ToSchema ConfigSchemaResponse where
|
||||||
declareNamedSchema _ =
|
declareNamedSchema _ = do
|
||||||
|
openApiSchemaRef <- declareOpenApiSchema
|
||||||
|
let otherSchemasSchema =
|
||||||
|
mempty
|
||||||
|
{ _schemaType = Just OpenApiObject,
|
||||||
|
_schemaNullable = Just False,
|
||||||
|
_schemaAdditionalProperties = Just $ AdditionalPropertiesSchema openApiSchemaRef
|
||||||
|
}
|
||||||
|
let schema =
|
||||||
|
mempty
|
||||||
|
{ _schemaType = Just OpenApiObject,
|
||||||
|
_schemaNullable = Just False,
|
||||||
|
_schemaRequired = ["configSchema", "otherSchemas"],
|
||||||
|
_schemaProperties =
|
||||||
|
InsOrdHashMap.fromList
|
||||||
|
[ ("configSchema", openApiSchemaRef),
|
||||||
|
("otherSchemas", Inline otherSchemasSchema)
|
||||||
|
]
|
||||||
|
}
|
||||||
pure $ NamedSchema (Just "ConfigSchemaResponse") schema
|
pure $ NamedSchema (Just "ConfigSchemaResponse") schema
|
||||||
where
|
|
||||||
schema :: Schema
|
-- | Declares the schema for the OpenAPI Schema type (and its dependent types) and
|
||||||
schema =
|
-- returns a reference that can be used to refer to it from other schemas.
|
||||||
|
--
|
||||||
|
-- This is a transcription of the schemas defined here:
|
||||||
|
-- https://raw.githubusercontent.com/OAI/OpenAPI-Specification/80c781e479f85ac67001ceb3e7e410e25d2a561b/schemas/v3.0/schema.json#/definitions/Schema
|
||||||
|
--
|
||||||
|
-- Unfortunately using external references to the above schema tends to make many
|
||||||
|
-- OpenAPI type generators choke, so importing the relevant schemas into our spec
|
||||||
|
-- is a pragmatic workaround.
|
||||||
|
declareOpenApiSchema :: Declare (Definitions Schema) (Referenced Schema)
|
||||||
|
declareOpenApiSchema = do
|
||||||
|
declare $
|
||||||
|
InsOrdHashMap.fromList
|
||||||
|
[ openApiSchema,
|
||||||
|
openApiReference,
|
||||||
|
openApiDiscriminator,
|
||||||
|
openApiExternalDocumentation,
|
||||||
|
openApiXml
|
||||||
|
]
|
||||||
|
pure . Ref $ Reference "OpenApiSchema"
|
||||||
|
where
|
||||||
|
openApiSchema :: (Text, Schema)
|
||||||
|
openApiSchema =
|
||||||
|
("OpenApiSchema",)
|
||||||
mempty
|
mempty
|
||||||
{ _schemaType = Just OpenApiObject,
|
{ _schemaType = Just OpenApiObject,
|
||||||
_schemaNullable = Just False,
|
|
||||||
_schemaRequired = ["configSchema", "otherSchemas"],
|
|
||||||
_schemaProperties =
|
_schemaProperties =
|
||||||
InsOrdHashMap.fromList
|
InsOrdHashMap.fromList
|
||||||
[ ("configSchema", openApiSchemaSchema),
|
[ ("title", Inline mempty {_schemaType = Just OpenApiString}),
|
||||||
("otherSchemas", Inline otherSchemasSchema)
|
("multipleOf", Inline mempty {_schemaType = Just OpenApiNumber, _schemaMinimum = Just 0, _schemaExclusiveMinimum = Just True}),
|
||||||
|
("maximum", Inline mempty {_schemaType = Just OpenApiNumber}),
|
||||||
|
("exclusiveMaximum", Inline mempty {_schemaType = Just OpenApiBoolean, _schemaDefault = Just $ Bool False}),
|
||||||
|
("minimum", Inline mempty {_schemaType = Just OpenApiNumber}),
|
||||||
|
("exclusiveMinimum", Inline mempty {_schemaType = Just OpenApiBoolean, _schemaDefault = Just $ Bool False}),
|
||||||
|
("maxLength", Inline mempty {_schemaType = Just OpenApiInteger, _schemaMinimum = Just 0}),
|
||||||
|
("minLength", Inline mempty {_schemaType = Just OpenApiInteger, _schemaMinimum = Just 0, _schemaDefault = Just $ Number 0}),
|
||||||
|
("pattern", Inline mempty {_schemaType = Just OpenApiString, _schemaFormat = Just "regex"}),
|
||||||
|
("maxItems", Inline mempty {_schemaType = Just OpenApiInteger, _schemaMinimum = Just 0}),
|
||||||
|
("minItems", Inline mempty {_schemaType = Just OpenApiInteger, _schemaMinimum = Just 0, _schemaDefault = Just $ Number 0}),
|
||||||
|
("uniqueItems", Inline mempty {_schemaType = Just OpenApiBoolean, _schemaDefault = Just $ Bool False}),
|
||||||
|
("maxProperties", Inline mempty {_schemaType = Just OpenApiInteger, _schemaMinimum = Just 0}),
|
||||||
|
("minProperties", Inline mempty {_schemaType = Just OpenApiInteger, _schemaMinimum = Just 0, _schemaDefault = Just $ Number 0}),
|
||||||
|
( "required",
|
||||||
|
Inline
|
||||||
|
mempty
|
||||||
|
{ _schemaType = Just OpenApiArray,
|
||||||
|
_schemaItems = Just . OpenApiItemsObject $ Inline mempty {_schemaType = Just OpenApiString},
|
||||||
|
_schemaMinItems = Just 1,
|
||||||
|
_schemaUniqueItems = Just True
|
||||||
|
}
|
||||||
|
),
|
||||||
|
( "enum",
|
||||||
|
Inline
|
||||||
|
mempty
|
||||||
|
{ _schemaType = Just OpenApiArray,
|
||||||
|
_schemaItems = Just . OpenApiItemsObject $ Inline mempty,
|
||||||
|
_schemaMinItems = Just 1,
|
||||||
|
_schemaUniqueItems = Just False
|
||||||
|
}
|
||||||
|
),
|
||||||
|
("type", Inline mempty {_schemaType = Just OpenApiString, _schemaEnum = Just ["array", "boolean", "integer", "number", "object", "string"]}),
|
||||||
|
("not", Inline mempty {_schemaOneOf = Just schemaOrReference}),
|
||||||
|
("allOf", Inline mempty {_schemaType = Just OpenApiArray, _schemaItems = Just . OpenApiItemsObject $ Inline mempty {_schemaOneOf = Just schemaOrReference}}),
|
||||||
|
("oneOf", Inline mempty {_schemaType = Just OpenApiArray, _schemaItems = Just . OpenApiItemsObject $ Inline mempty {_schemaOneOf = Just schemaOrReference}}),
|
||||||
|
("anyOf", Inline mempty {_schemaType = Just OpenApiArray, _schemaItems = Just . OpenApiItemsObject $ Inline mempty {_schemaOneOf = Just schemaOrReference}}),
|
||||||
|
("items", Inline mempty {_schemaOneOf = Just schemaOrReference}),
|
||||||
|
("properties", Inline mempty {_schemaType = Just OpenApiObject, _schemaAdditionalProperties = Just . AdditionalPropertiesSchema $ Inline mempty {_schemaOneOf = Just schemaOrReference}}),
|
||||||
|
( "additionalProperties",
|
||||||
|
Inline
|
||||||
|
mempty
|
||||||
|
{ _schemaAdditionalProperties = Just . AdditionalPropertiesSchema $ Inline mempty {_schemaOneOf = Just $ schemaOrReference <> [Inline mempty {_schemaType = Just OpenApiBoolean}]},
|
||||||
|
_schemaDefault = Just $ Bool True
|
||||||
|
}
|
||||||
|
),
|
||||||
|
("description", Inline mempty {_schemaType = Just OpenApiString}),
|
||||||
|
("format", Inline mempty {_schemaType = Just OpenApiString}),
|
||||||
|
("default", Inline mempty),
|
||||||
|
("nullable", Inline mempty {_schemaType = Just OpenApiBoolean, _schemaDefault = Just $ Bool False}),
|
||||||
|
("discriminator", Ref . Reference $ fst openApiDiscriminator),
|
||||||
|
("readOnly", Inline mempty {_schemaType = Just OpenApiBoolean, _schemaDefault = Just $ Bool False}),
|
||||||
|
("writeOnly", Inline mempty {_schemaType = Just OpenApiBoolean, _schemaDefault = Just $ Bool False}),
|
||||||
|
("example", Inline mempty),
|
||||||
|
("externalDocs", Ref . Reference $ fst openApiExternalDocumentation),
|
||||||
|
("deprecated", Inline mempty {_schemaType = Just OpenApiBoolean, _schemaDefault = Just $ Bool False}),
|
||||||
|
("xml", Ref . Reference $ fst openApiXml)
|
||||||
|
],
|
||||||
|
-- Note: Technically OpenAPI schemas should be able to define extension properties but since OpenAPI itself doesn't
|
||||||
|
-- support defining patternProperties, I can't define them here. 😢
|
||||||
|
-- "patternProperties": { "^x-": {} }
|
||||||
|
-- _schemaPatternProperties =
|
||||||
|
_schemaAdditionalProperties = Just $ AdditionalPropertiesAllowed False
|
||||||
|
}
|
||||||
|
|
||||||
|
openApiReference :: (Text, Schema)
|
||||||
|
openApiReference =
|
||||||
|
("OpenApiReference",)
|
||||||
|
mempty
|
||||||
|
{ _schemaType = Just OpenApiObject,
|
||||||
|
_schemaRequired = ["$ref"],
|
||||||
|
-- Note: This is technically defined using "patternProperties" with the property name regex ^\$ref$
|
||||||
|
-- but OpenAPI doesn't support patternProperties ironically, so this is close enough
|
||||||
|
_schemaProperties = InsOrdHashMap.fromList [("$ref", Inline mempty {_schemaType = Just OpenApiString, _schemaFormat = Just "uri-reference"})]
|
||||||
|
}
|
||||||
|
|
||||||
|
schemaOrReference :: [Referenced Schema]
|
||||||
|
schemaOrReference = [Ref . Reference $ fst openApiSchema, Ref . Reference $ fst openApiReference]
|
||||||
|
|
||||||
|
openApiDiscriminator :: (Text, Schema)
|
||||||
|
openApiDiscriminator =
|
||||||
|
("OpenApiDiscriminator",)
|
||||||
|
mempty
|
||||||
|
{ _schemaType = Just OpenApiObject,
|
||||||
|
_schemaRequired = ["propertyName"],
|
||||||
|
_schemaProperties =
|
||||||
|
InsOrdHashMap.fromList
|
||||||
|
[ ("propertyName", Inline mempty {_schemaType = Just OpenApiString}),
|
||||||
|
("mapping", Inline mempty {_schemaType = Just OpenApiObject, _schemaAdditionalProperties = Just . AdditionalPropertiesSchema $ Inline mempty {_schemaType = Just OpenApiString}})
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
otherSchemasSchema :: Schema
|
openApiExternalDocumentation :: (Text, Schema)
|
||||||
otherSchemasSchema =
|
openApiExternalDocumentation =
|
||||||
|
("OpenApiExternalDocumentation",)
|
||||||
mempty
|
mempty
|
||||||
{ _schemaType = Just OpenApiObject,
|
{ _schemaType = Just OpenApiObject,
|
||||||
_schemaNullable = Just False,
|
_schemaRequired = ["url"],
|
||||||
_schemaAdditionalProperties = Just $ AdditionalPropertiesSchema openApiSchemaSchema
|
_schemaProperties =
|
||||||
|
InsOrdHashMap.fromList
|
||||||
|
[ ("description", Inline mempty {_schemaType = Just OpenApiString}),
|
||||||
|
("url", Inline mempty {_schemaType = Just OpenApiString, _schemaFormat = Just "uri-reference"})
|
||||||
|
],
|
||||||
|
-- Note: Technically external docs should be able to define extension properties but since OpenAPI itself doesn't
|
||||||
|
-- support defining patternProperties, I can't define them here. 😢
|
||||||
|
-- "patternProperties": { "^x-": {} }
|
||||||
|
-- _schemaPatternProperties =
|
||||||
|
_schemaAdditionalProperties = Just $ AdditionalPropertiesAllowed False
|
||||||
}
|
}
|
||||||
|
|
||||||
openApiSchemaSchema :: Referenced Schema
|
openApiXml :: (Text, Schema)
|
||||||
openApiSchemaSchema =
|
openApiXml =
|
||||||
Ref (Reference "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/80c781e479f85ac67001ceb3e7e410e25d2a561b/schemas/v3.0/schema.json#/definitions/Schema")
|
("OpenApiXml",)
|
||||||
|
mempty
|
||||||
|
{ _schemaType = Just OpenApiObject,
|
||||||
|
_schemaProperties =
|
||||||
|
InsOrdHashMap.fromList
|
||||||
|
[ ("name", Inline mempty {_schemaType = Just OpenApiString}),
|
||||||
|
("namespace", Inline mempty {_schemaType = Just OpenApiString, _schemaFormat = Just "uri"}),
|
||||||
|
("prefix", Inline mempty {_schemaType = Just OpenApiString}),
|
||||||
|
("attribute", Inline mempty {_schemaType = Just OpenApiBoolean, _schemaDefault = Just $ Bool False}),
|
||||||
|
("wrapped", Inline mempty {_schemaType = Just OpenApiBoolean, _schemaDefault = Just $ Bool False})
|
||||||
|
],
|
||||||
|
-- Note: Technically XML should be able to define extension properties but since OpenAPI itself doesn't
|
||||||
|
-- support defining patternProperties, I can't define them here. 😢
|
||||||
|
-- "patternProperties": { "^x-": {} }
|
||||||
|
-- _schemaPatternProperties =
|
||||||
|
_schemaAdditionalProperties = Just $ AdditionalPropertiesAllowed False
|
||||||
|
}
|
||||||
|
|
||||||
-- | Rewrites the config schema internal refs to the form that openapi3 expects when it deserialized them
|
-- | Rewrites the config schema internal refs to the form that openapi3 expects when it deserialized them
|
||||||
--
|
--
|
||||||
@ -157,26 +307,3 @@ rewriteSchemaRefs rewriteRefText schemaObj =
|
|||||||
validateConfigAgainstConfigSchema :: ConfigSchemaResponse -> Config -> [ValidationError]
|
validateConfigAgainstConfigSchema :: ConfigSchemaResponse -> Config -> [ValidationError]
|
||||||
validateConfigAgainstConfigSchema ConfigSchemaResponse {..} (Config config) =
|
validateConfigAgainstConfigSchema ConfigSchemaResponse {..} (Config config) =
|
||||||
OpenApi.validateJSON _csrOtherSchemas _csrConfigSchema (Object config)
|
OpenApi.validateJSON _csrOtherSchemas _csrConfigSchema (Object config)
|
||||||
|
|
||||||
-- | Fixes any refs in schemas that are external refs to an http-based URL.
|
|
||||||
-- Note that this is limited to schemas in the components/schemas section.
|
|
||||||
-- This is used to specifically address the external refs defined by the
|
|
||||||
-- OpenAPI schema spec of the 'ConfigSchemaResponse' type.
|
|
||||||
--
|
|
||||||
-- This works around a limitation in the openapi3 library where it does not
|
|
||||||
-- understand the concept of external refs and will always assume any defined
|
|
||||||
-- ref refers to a schema inside the top level OpenApi document itself.
|
|
||||||
-- Practically, this means that #/components/schemas/ gets mashed onto the
|
|
||||||
-- front of any external ref :(
|
|
||||||
fixExternalSchemaRefsInComponentSchemas :: Value -> Value
|
|
||||||
fixExternalSchemaRefsInComponentSchemas openApiObj =
|
|
||||||
openApiObj
|
|
||||||
& key "components" . key "schemas" . members %~ fixExternalSchemaRefsInSchema
|
|
||||||
|
|
||||||
fixExternalSchemaRefsInSchema :: Value -> Value
|
|
||||||
fixExternalSchemaRefsInSchema = rewriteSchemaRefs fixExternalHttpSchemaRef
|
|
||||||
|
|
||||||
fixExternalHttpSchemaRef :: Text -> Text
|
|
||||||
fixExternalHttpSchemaRef = \case
|
|
||||||
(Text.stripPrefix "#/components/schemas/http" -> Just suffix) -> "http" <> suffix
|
|
||||||
other -> other
|
|
||||||
|
@ -113,7 +113,10 @@ deriving via Autodocodec Field instance ToSchema Field
|
|||||||
-- endpoint encoded as a list of JSON objects.
|
-- endpoint encoded as a list of JSON objects.
|
||||||
newtype QueryResponse = QueryResponse {getQueryResponse :: [Object]}
|
newtype QueryResponse = QueryResponse {getQueryResponse :: [Object]}
|
||||||
deriving newtype (Eq, Ord, Show, NFData)
|
deriving newtype (Eq, Ord, Show, NFData)
|
||||||
deriving (ToJSON, FromJSON, ToSchema) via Autodocodec [Object]
|
deriving (ToJSON, FromJSON, ToSchema) via Autodocodec QueryResponse
|
||||||
|
|
||||||
|
instance HasCodec QueryResponse where
|
||||||
|
codec = named "QueryResponse" $ dimapCodec QueryResponse getQueryResponse codec
|
||||||
|
|
||||||
$(makeLenses ''QueryRequest)
|
$(makeLenses ''QueryRequest)
|
||||||
$(makeLenses ''Query)
|
$(makeLenses ''Query)
|
||||||
|
@ -31,5 +31,5 @@ data Type
|
|||||||
|
|
||||||
instance HasCodec Type where
|
instance HasCodec Type where
|
||||||
codec =
|
codec =
|
||||||
named "Type" $
|
named "ScalarType" $
|
||||||
disjointStringConstCodec [(StringTy, "string"), (NumberTy, "number"), (BoolTy, "bool")]
|
disjointStringConstCodec [(StringTy, "string"), (NumberTy, "number"), (BoolTy, "bool")]
|
||||||
|
@ -42,7 +42,7 @@ import Data.Text.Extended
|
|||||||
import Data.Text.Lazy qualified as LT
|
import Data.Text.Lazy qualified as LT
|
||||||
import Data.Text.Lazy.Encoding qualified as TL
|
import Data.Text.Lazy.Encoding qualified as TL
|
||||||
import GHC.Stats.Extended qualified as RTS
|
import GHC.Stats.Extended qualified as RTS
|
||||||
import Hasura.Backends.DataConnector.API (openApiSchemaJson)
|
import Hasura.Backends.DataConnector.API (openApiSchema)
|
||||||
import Hasura.Backends.Postgres.Execute.Types
|
import Hasura.Backends.Postgres.Execute.Types
|
||||||
import Hasura.Base.Error
|
import Hasura.Base.Error
|
||||||
import Hasura.EncJSON
|
import Hasura.EncJSON
|
||||||
@ -1078,7 +1078,7 @@ httpApp setupHook corsCfg serverCtx enableConsole consoleAssetsDir enableTelemet
|
|||||||
spockAction encodeQErr id $
|
spockAction encodeQErr id $
|
||||||
mkGetHandler $ do
|
mkGetHandler $ do
|
||||||
onlyAdmin
|
onlyAdmin
|
||||||
return (emptyHttpLogMetadata @m, JSONResp $ HttpResponse (encJFromJValue openApiSchemaJson) [])
|
return (emptyHttpLogMetadata @m, JSONResp $ HttpResponse (encJFromJValue openApiSchema) [])
|
||||||
Spock.get "api/swagger/json" $
|
Spock.get "api/swagger/json" $
|
||||||
spockAction encodeQErr id $
|
spockAction encodeQErr id $
|
||||||
mkGetHandler $ do
|
mkGetHandler $ do
|
||||||
|
@ -65,8 +65,8 @@ spec = do
|
|||||||
|]
|
|]
|
||||||
testToFromJSON val jsonVal
|
testToFromJSON val jsonVal
|
||||||
|
|
||||||
it "produces the correct OpenAPI Spec once external schema refs are fixed up" $
|
it "OpenAPI spec is as expected" $
|
||||||
fixExternalSchemaRefsInSchema (toJSON $ toSchema (Proxy @ConfigSchemaResponse))
|
toJSON (toSchema (Proxy @ConfigSchemaResponse))
|
||||||
`shouldBe` [aesonQQ|
|
`shouldBe` [aesonQQ|
|
||||||
{
|
{
|
||||||
"required": [
|
"required": [
|
||||||
@ -77,11 +77,11 @@ spec = do
|
|||||||
"nullable": false,
|
"nullable": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
"configSchema": {
|
"configSchema": {
|
||||||
"$ref": "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/80c781e479f85ac67001ceb3e7e410e25d2a561b/schemas/v3.0/schema.json#/definitions/Schema"
|
"$ref": "#/components/schemas/OpenApiSchema"
|
||||||
},
|
},
|
||||||
"otherSchemas": {
|
"otherSchemas": {
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
"$ref": "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/80c781e479f85ac67001ceb3e7e410e25d2a561b/schemas/v3.0/schema.json#/definitions/Schema"
|
"$ref": "#/components/schemas/OpenApiSchema"
|
||||||
},
|
},
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"nullable": false
|
"nullable": false
|
||||||
|
@ -6,7 +6,7 @@ import Control.Monad ((>=>))
|
|||||||
import Data.Aeson.Text (encodeToLazyText)
|
import Data.Aeson.Text (encodeToLazyText)
|
||||||
import Data.Proxy (Proxy (..))
|
import Data.Proxy (Proxy (..))
|
||||||
import Data.Text.Lazy.IO qualified as Text
|
import Data.Text.Lazy.IO qualified as Text
|
||||||
import Hasura.Backends.DataConnector.API (Routes (..), apiClient, openApiSchemaJson)
|
import Hasura.Backends.DataConnector.API (Routes (..), apiClient, openApiSchema)
|
||||||
import Hasura.Backends.DataConnector.API qualified as API
|
import Hasura.Backends.DataConnector.API qualified as API
|
||||||
import Network.HTTP.Client (defaultManagerSettings, newManager)
|
import Network.HTTP.Client (defaultManagerSettings, newManager)
|
||||||
import Servant.API (NamedRoutes)
|
import Servant.API (NamedRoutes)
|
||||||
@ -38,7 +38,7 @@ main = do
|
|||||||
agentCapabilities <- getAgentCapabilities api _toAgentCapabilities
|
agentCapabilities <- getAgentCapabilities api _toAgentCapabilities
|
||||||
runSpec (tests api testSourceName _toAgentConfig agentCapabilities) (applyTestConfig defaultConfig testOptions) >>= evaluateSummary
|
runSpec (tests api testSourceName _toAgentConfig agentCapabilities) (applyTestConfig defaultConfig testOptions) >>= evaluateSummary
|
||||||
ExportOpenAPISpec ->
|
ExportOpenAPISpec ->
|
||||||
Text.putStrLn $ encodeToLazyText openApiSchemaJson
|
Text.putStrLn $ encodeToLazyText openApiSchema
|
||||||
|
|
||||||
pure ()
|
pure ()
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ import Data.Aeson qualified as Aeson
|
|||||||
import Data.IORef qualified as I
|
import Data.IORef qualified as I
|
||||||
import Harness.Backend.DataConnector.MockAgent
|
import Harness.Backend.DataConnector.MockAgent
|
||||||
import Harness.GraphqlEngine qualified as GraphqlEngine
|
import Harness.GraphqlEngine qualified as GraphqlEngine
|
||||||
|
import Harness.Http (healthCheck)
|
||||||
import Harness.Quoter.Yaml (shouldReturnYaml, yaml)
|
import Harness.Quoter.Yaml (shouldReturnYaml, yaml)
|
||||||
import Harness.Test.Context (BackendType (DataConnector), Options, defaultBackendTypeString)
|
import Harness.Test.Context (BackendType (DataConnector), Options, defaultBackendTypeString)
|
||||||
import Harness.TestEnvironment (TestEnvironment)
|
import Harness.TestEnvironment (TestEnvironment)
|
||||||
@ -48,10 +49,11 @@ dataconnector:
|
|||||||
mockBackendConfig :: Aeson.Value
|
mockBackendConfig :: Aeson.Value
|
||||||
mockBackendConfig =
|
mockBackendConfig =
|
||||||
let backendType = defaultBackendTypeString $ DataConnector
|
let backendType = defaultBackendTypeString $ DataConnector
|
||||||
|
agentUri = "http://127.0.0.1:" <> show mockAgentPort <> "/"
|
||||||
in [yaml|
|
in [yaml|
|
||||||
dataconnector:
|
dataconnector:
|
||||||
*backendType:
|
*backendType:
|
||||||
uri: "http://127.0.0.1:65006/"
|
uri: *agentUri
|
||||||
|]
|
|]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
@ -114,6 +116,7 @@ mkLocalTestEnvironmentMock _ = do
|
|||||||
maeConfig <- I.newIORef chinookMock
|
maeConfig <- I.newIORef chinookMock
|
||||||
maeQuery <- I.newIORef Nothing
|
maeQuery <- I.newIORef Nothing
|
||||||
maeThreadId <- forkIO $ runMockServer maeConfig maeQuery
|
maeThreadId <- forkIO $ runMockServer maeConfig maeQuery
|
||||||
|
healthCheck $ "http://127.0.0.1:" <> show mockAgentPort <> "/healthz"
|
||||||
pure $ MockAgentEnvironment {..}
|
pure $ MockAgentEnvironment {..}
|
||||||
|
|
||||||
-- | Load the agent schema into HGE.
|
-- | Load the agent schema into HGE.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
module Harness.Backend.DataConnector.MockAgent
|
module Harness.Backend.DataConnector.MockAgent
|
||||||
( MockConfig (..),
|
( MockConfig (..),
|
||||||
chinookMock,
|
chinookMock,
|
||||||
|
mockAgentPort,
|
||||||
runMockServer,
|
runMockServer,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
@ -220,12 +221,22 @@ mockQueryHandler :: I.IORef MockConfig -> I.IORef (Maybe API.QueryRequest) -> AP
|
|||||||
mockQueryHandler mcfg mquery _sourceName _cfg query = liftIO $ do
|
mockQueryHandler mcfg mquery _sourceName _cfg query = liftIO $ do
|
||||||
handler <- fmap _queryResponse $ I.readIORef mcfg
|
handler <- fmap _queryResponse $ I.readIORef mcfg
|
||||||
I.writeIORef mquery (Just query)
|
I.writeIORef mquery (Just query)
|
||||||
pure $ handler (error "WTF DUDE")
|
pure $ handler query
|
||||||
|
|
||||||
dcMockableServer :: I.IORef MockConfig -> I.IORef (Maybe API.QueryRequest) -> Server API.Api
|
type HealthcheckApi =
|
||||||
dcMockableServer mcfg mquery = mockCapabilitiesHandler mcfg :<|> mockSchemaHandler mcfg :<|> mockQueryHandler mcfg mquery
|
"healthz"
|
||||||
|
:> Get '[JSON] ()
|
||||||
|
|
||||||
|
healthcheckHandler :: Handler ()
|
||||||
|
healthcheckHandler = pure ()
|
||||||
|
|
||||||
|
dcMockableServer :: I.IORef MockConfig -> I.IORef (Maybe API.QueryRequest) -> Server (API.Api :<|> HealthcheckApi)
|
||||||
|
dcMockableServer mcfg mquery = (mockCapabilitiesHandler mcfg :<|> mockSchemaHandler mcfg :<|> mockQueryHandler mcfg mquery) :<|> healthcheckHandler
|
||||||
|
|
||||||
|
mockAgentPort :: Warp.Port
|
||||||
|
mockAgentPort = 65006
|
||||||
|
|
||||||
runMockServer :: I.IORef MockConfig -> I.IORef (Maybe API.QueryRequest) -> IO ()
|
runMockServer :: I.IORef MockConfig -> I.IORef (Maybe API.QueryRequest) -> IO ()
|
||||||
runMockServer mcfg mquery = do
|
runMockServer mcfg mquery = do
|
||||||
let app = serve (Proxy :: Proxy API.Api) $ dcMockableServer mcfg mquery
|
let app = serve (Proxy :: Proxy (API.Api :<|> HealthcheckApi)) $ dcMockableServer mcfg mquery
|
||||||
Warp.run 65006 app
|
Warp.run mockAgentPort app
|
||||||
|
Loading…
Reference in New Issue
Block a user