diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index c22d087b08..507f08c6e7 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -1,4 +1,4 @@ -name: PostgreSQL tests +name: LaunchQL tests on: push: workflow_dispatch: @@ -37,29 +37,15 @@ jobs: --health-retries 5 steps: - # - name: Install Git - # run: apk add --no-cache git - + # TODO remove deps on git config - name: Configure Git (for tests) run: | git config --global user.name "CI Test User" git config --global user.email "ci@example.com" - # - name: Install Sqitch on Alpine - # run: | - # apk add --no-cache curl make perl perl-utils perl-dev build-base \ - # libpq libpq-dev postgresql-dev \ - # perl-dbd-pg perl-dbi perl-dbd-sqlite \ - # cpanminus - - # cpanm --notest --quiet App::Sqitch - - name: checkout uses: actions/checkout@v4 - # - name: deps - # run: apk update && apk add bash git python3-dev make g++ - - name: deps run: yarn @@ -92,14 +78,14 @@ jobs: - name: launchql/uuid-stream run: cd ./packages/uuid-stream && yarn test - - name: launchql/query-builder - run: cd ./packages/query-builder && yarn test - - name: launchql/introspectron run: cd ./packages/introspectron && yarn test - - name: launchql/react-client - run: cd ./packages/react-client && yarn test + - name: launchql/query-builder + run: cd ./packages/query-builder && yarn test + + - name: launchql/query + run: cd ./packages/query && yarn test - name: launchql/launchql-gen run: cd ./packages/launchql-gen && yarn test diff --git a/packages/introspectron/package.json b/packages/introspectron/package.json index 0edf7f075f..80c6f5e865 100644 --- a/packages/introspectron/package.json +++ b/packages/introspectron/package.json @@ -30,7 +30,6 @@ "test:watch": "jest --watch" }, "dependencies": { - "graphql-tag": "2.12.5", - "lodash": "4.17.20" + "graphql-tag": "2.12.5" } } \ No newline at end of file diff --git a/packages/introspectron/src/introspect.ts b/packages/introspectron/src/introspect.ts index 347043d794..24ab9ea576 100644 --- a/packages/introspectron/src/introspect.ts +++ b/packages/introspectron/src/introspect.ts @@ -1,7 +1,6 @@ // @ts-nocheck import { makeIntrospectionQuery } from './query'; import { parseTags } from './utils'; -import flatMap from 'lodash/flatMap'; export const introspect = async ( pgClient, @@ -66,8 +65,7 @@ export const introspect = async ( }); }); - const extensionConfigurationClassIds = flatMap( - result.extension, + const extensionConfigurationClassIds = result.extension.flatMap( (e) => e.configurationClassIds ); result.class.forEach((klass) => { diff --git a/packages/react-client/README.md b/packages/query/README.md similarity index 55% rename from packages/react-client/README.md rename to packages/query/README.md index 9bdda8a033..dd3e06754c 100644 --- a/packages/react-client/README.md +++ b/packages/query/README.md @@ -1,4 +1,4 @@ -# @launchql/react-client +# `@launchql/query`
-Generate GraphQL mutations/queries +> Fluent GraphQL query and mutation builder for PostGraphile-based schemas. + +## Installation ```sh -npm install @launchql/react-client +npm install @launchql/query ``` +## Why Use `@launchql/query`? + +* ⚡ Build complex, nested GraphQL queries fluently +* ✅ Schema-aware via introspection (PostGraphile optimized) +* 🧠 Prevents common query syntax issues +* 🧩 Designed for composability and clean syntax + ## Usage -```js -import { Client } from '@launchql/react-client'; +```ts +import { Client } from '@launchql/query'; const client = new Client({ - introspection: { ...queries, ...mutations } + introspection: { ...queries, ...mutations } // provide your GraphQL schema metadata }); - const result = client - .query('Action') - .edges(true) - .getMany({ - select: { - id: true, - name: true, - photo: true, - title: true, - actionResults: { - select: { - id: true, - actionId: true - }, - variables: { - first: 10, - before: null, - filter: { - name: { - in: ['abc', 'def'] - }, - actionId: { equalTo: 'dc310161-7a42-4b93-6a56-9fa48adcad7e' } +const result = client + .query('Action') + .edges(true) + .getMany({ + select: { + id: true, + name: true, + photo: true, + title: true, + actionResults: { + select: { + id: true, + actionId: true + }, + variables: { + first: 10, + before: null, + filter: { + name: { + in: ['abc', 'def'] + }, + actionId: { + equalTo: 'dc310161-7a42-4b93-6a56-9fa48adcad7e' } } } } - }) - .print(); + } + }) + .print(); ``` -# output +## Output -```gql +```graphql query getActionsQuery( $first: Int $last: Int @@ -111,4 +122,4 @@ query getActionsQuery( } } } -``` +``` \ No newline at end of file diff --git a/packages/react-client/__fixtures__/api/introspection.json b/packages/query/__fixtures__/api/introspection.json similarity index 100% rename from packages/react-client/__fixtures__/api/introspection.json rename to packages/query/__fixtures__/api/introspection.json diff --git a/packages/react-client/__fixtures__/api/meta-obj.json b/packages/query/__fixtures__/api/meta-obj.json similarity index 100% rename from packages/react-client/__fixtures__/api/meta-obj.json rename to packages/query/__fixtures__/api/meta-obj.json diff --git a/packages/react-client/__fixtures__/api/meta-schema.json b/packages/query/__fixtures__/api/meta-schema.json similarity index 100% rename from packages/react-client/__fixtures__/api/meta-schema.json rename to packages/query/__fixtures__/api/meta-schema.json diff --git a/packages/react-client/__fixtures__/generate-fixtures.js b/packages/query/__fixtures__/generate-fixtures.js similarity index 90% rename from packages/react-client/__fixtures__/generate-fixtures.js rename to packages/query/__fixtures__/generate-fixtures.js index 136632fb64..8cd92a9c76 100644 --- a/packages/react-client/__fixtures__/generate-fixtures.js +++ b/packages/query/__fixtures__/generate-fixtures.js @@ -1,7 +1,7 @@ const path = require('path'); const fs = require('fs'); const intro = require('introspectron'); -const client = require('@launchql/react-client'); +const builder = require('@launchql/query'); function generateIntrospectionFixture() { const inDir = path.resolve( @@ -35,7 +35,7 @@ function generateMetaObjectFixture() { const outDir = path.resolve(__dirname, './api/meta-obj.json'); fs.readFile(inDir, { encoding: 'utf8' }, (err, data) => { if (err) return console.log(err); - const converted = client.MetaObject.convertFromMetaSchema(JSON.parse(data)); + const converted = builder.MetaObject.convertFromMetaSchema(JSON.parse(data)); fs.writeFile(outDir, JSON.stringify(converted), (err) => { if (err) return console.log(err); console.log('DONE'); diff --git a/packages/react-client/__tests__/__snapshots__/client.test.ts.snap b/packages/query/__tests__/__snapshots__/builder.test.ts.snap similarity index 100% rename from packages/react-client/__tests__/__snapshots__/client.test.ts.snap rename to packages/query/__tests__/__snapshots__/builder.test.ts.snap diff --git a/packages/react-client/__tests__/__snapshots__/meta-object.test.ts.snap b/packages/query/__tests__/__snapshots__/meta-object.test.ts.snap similarity index 100% rename from packages/react-client/__tests__/__snapshots__/meta-object.test.ts.snap rename to packages/query/__tests__/__snapshots__/meta-object.test.ts.snap diff --git a/packages/react-client/__tests__/client.test.ts b/packages/query/__tests__/builder.test.ts similarity index 86% rename from packages/react-client/__tests__/client.test.ts rename to packages/query/__tests__/builder.test.ts index 492c215f46..0e30aae528 100644 --- a/packages/react-client/__tests__/client.test.ts +++ b/packages/query/__tests__/builder.test.ts @@ -1,16 +1,16 @@ // @ts-nocheck import introspection from '../__fixtures__/api/introspection.json'; import metaObject from '../__fixtures__/api/meta-obj.json'; -import { Client } from '../src'; +import { QueryBuilder } from '../src'; describe('getMany', () => { it('should select only scalar fields by default', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client.query('Action').getMany().print(); + const result = builder.query('Action').getMany().print(); expect(result._hash).toMatchSnapshot(); expect(result._queryName).toMatchSnapshot(); @@ -22,12 +22,12 @@ describe('getMany', () => { }); it('should whitelist selected fields', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client + const result = builder .query('Action') .getMany({ select: { @@ -60,12 +60,12 @@ describe('getMany', () => { }); it('should select totalCount in subfields by default', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client + const result = builder .query('Action') .getMany({ select: { @@ -98,12 +98,12 @@ it('should select totalCount in subfields by default', () => { }); it('selects relation field', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client + const result = builder .query('Action') .getMany({ select: { @@ -140,24 +140,24 @@ it('selects relation field', () => { }); it('selects all scalar fields of junction table by default', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client.query('ActionGoal').getMany().print(); + const result = builder.query('ActionGoal').getMany().print(); expect(/(actionId)|(goalId)|(ownerId)/.test(result._hash)).toBe(true); expect(result._hash).toMatchSnapshot(); }); it('selects belongsTo relation field', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client + const result = builder .query('Action') .getMany({ select: { @@ -177,12 +177,12 @@ it('selects belongsTo relation field', () => { }); it('selects non-scalar custom types', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client + const result = builder .query('Action') .getMany({ select: { @@ -199,11 +199,11 @@ it('selects non-scalar custom types', () => { }); it('getMany edges', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client + const result = builder .query('Action') .edges(true) .getMany({ @@ -236,11 +236,11 @@ it('getMany edges', () => { }); it('getOne', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client + const result = builder .query('Action') .getOne({ select: { @@ -272,12 +272,12 @@ it('getOne', () => { }); it('getAll', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client + const result = builder .query('Action') .all({ select: { @@ -309,22 +309,22 @@ it('getAll', () => { }); it('create with default scalar selection', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client.query('Action').create().print(); + const result = builder.query('Action').create().print(); expect(result._hash).toMatchSnapshot(); expect(result._queryName).toMatchSnapshot(); }); it('create with custom selection', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client + const result = builder .query('Action') .create({ select: { @@ -342,21 +342,21 @@ it('create with custom selection', () => { }); it('update with default scalar selection', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client.query('Action').update().print(); + const result = builder.query('Action').update().print(); expect(result._hash).toMatchSnapshot(); expect(result._queryName).toMatchSnapshot(); }); it('update with custom selection', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client + const result = builder .query('Action') .update({ select: { @@ -373,22 +373,22 @@ it('update with custom selection', () => { }); it('delete', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client.query('Action').delete().print(); + const result = builder.query('Action').delete().print(); expect(result._hash).toMatchSnapshot(); expect(result._queryName).toMatchSnapshot(); }); it('expands further selections of custom ast fields in nested selection', () => { - const client = new Client({ + const builder = new QueryBuilder({ meta: metaObject, introspection }); - const result = client + const result = builder .query('ActionGoal') .getMany({ select: { diff --git a/packages/react-client/__tests__/meta-object.test.ts b/packages/query/__tests__/meta-object.test.ts similarity index 100% rename from packages/react-client/__tests__/meta-object.test.ts rename to packages/query/__tests__/meta-object.test.ts diff --git a/packages/react-client/jest.config.js b/packages/query/jest.config.js similarity index 100% rename from packages/react-client/jest.config.js rename to packages/query/jest.config.js diff --git a/packages/react-client/package.json b/packages/query/package.json similarity index 90% rename from packages/react-client/package.json rename to packages/query/package.json index f685085ee8..e6fd4e2e7d 100644 --- a/packages/react-client/package.json +++ b/packages/query/package.json @@ -1,7 +1,7 @@ { - "name": "@launchql/react-client", + "name": "@launchql/query", "version": "2.0.0", - "description": "LaunchQL React Client", + "description": "LaunchQL Query", "author": "Dan Lynch