From 62e5db0159311970a4c7a24b400bcfe57a98ae28 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 07:52:26 +1200 Subject: [PATCH 01/21] Add vue-class-component to optionalDependencies --- package-lock.json | 5 +++++ package.json | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/package-lock.json b/package-lock.json index e4e74df..526da95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10156,6 +10156,11 @@ } } }, + "vue-class-component": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-7.2.6.tgz", + "integrity": "sha512-+eaQXVrAm/LldalI272PpDe3+i4mPis0ORiMYxF6Ae4hyuCh15W8Idet7wPUEs4N4YptgFHGys4UrgNQOMyO6w==" + }, "vue-eslint-parser": { "version": "7.10.0", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.10.0.tgz", diff --git a/package.json b/package.json index 70e87b1..08a2f24 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,9 @@ "lodash.isplainobject": "^4.0", "lodash.mapvalues": "^4.6" }, + "optionalDependencies": { + "vue-class-component": "^7.2" + }, "peerDependencies": { "apollo-client": ">=2.6", "apollo-link": ">=1.2", @@ -68,6 +71,7 @@ "typescript": "4.2.4", "vue": "2.6.14", "vue-apollo": "3.0.7", + "vue-class-component": "7.2.6", "vue-jest": "3.0.7" }, "engines": { From 4d55c37949286da9388ea78d40932b9eb42a0334 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 07:55:23 +1200 Subject: [PATCH 02/21] Add SmartQuery decorator --- src/decorator/SmartQuery.ts | 20 +++++++++++++ src/decorator/index.ts | 5 ++++ src/index.ts | 1 + src/query.ts | 60 +++++++++++++++++++++++++++++-------- 4 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 src/decorator/SmartQuery.ts create mode 100644 src/decorator/index.ts diff --git a/src/decorator/SmartQuery.ts b/src/decorator/SmartQuery.ts new file mode 100644 index 0000000..d5be829 --- /dev/null +++ b/src/decorator/SmartQuery.ts @@ -0,0 +1,20 @@ +/* + * Based on https://github.com/chanlito/vue-apollo-decorator by chanlito ❤️ + */ + +import { ApolloError, OperationVariables } from 'apollo-client'; +import { DocumentNode } from 'graphql'; +import Vue from 'vue'; +import { createDecorator, VueDecorator } from 'vue-class-component'; +import { VueApolloSmartQueryOptions } from '../query'; + +export function SmartQuery( + options: TApp extends Vue + ? VueApolloSmartQueryOptions + : DocumentNode, +): VueDecorator { + return createDecorator((componentOptions: any, k: string) => { + componentOptions.apollo = componentOptions.apollo || {}; + componentOptions.apollo[k] = options; + }); +} diff --git a/src/decorator/index.ts b/src/decorator/index.ts new file mode 100644 index 0000000..3baa3dd --- /dev/null +++ b/src/decorator/index.ts @@ -0,0 +1,5 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './SmartQuery'; diff --git a/src/index.ts b/src/index.ts index 2e52d57..4acb9e5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,3 +8,4 @@ export * from './mutation'; export * from './query'; export * from './subscription'; export * from './types'; +export * from './decorator/index'; diff --git a/src/query.ts b/src/query.ts index 19b6cc8..6a47b66 100644 --- a/src/query.ts +++ b/src/query.ts @@ -1,39 +1,75 @@ -import { VueApolloQueryDefinition, ErrorHandler } from 'vue-apollo/types/options'; import { ApolloError, OperationVariables } from 'apollo-client'; import { DocumentNode } from 'graphql'; +import { ErrorHandler, VueApolloQueryDefinition, VueApolloSubscribeToMoreOptions } from 'vue-apollo/types/options'; import { Vue } from 'vue/types/vue'; import { ApolloOperationErrorHandlerFunction } from './types'; +type OverrideThis = F extends (...args: infer A) => infer B ? (this: T, ...args: A) => B : F; + +type OverrideAllThis = { + [key in keyof O]: OverrideThis; +}; + +type VueApolloQueryDefinitionWithoutVariablesAndSubscribeToMore = Omit< + VueApolloQueryDefinition, + 'subscribeToMore' | 'variables' +>; + +type SubscribeToMoreOptionsPatched = OverrideAllThis< + Omit, 'updateQuery' | 'variables'>, + TComponent +> & { + variables?: (this: TComponent) => any; + updateQuery?: UpdateQueryFn; // TODO: How should we pass subscript data & variables types? +}; + +type UpdateQueryFn = ( + this: TComponent, + previousQueryResult: TResult, + options: { + subscriptionData: { + data: TSubscriptionData; + }; + variables?: TSubscriptionVariables; + }, +) => TResult; + +export interface VueApolloQueryDefinitionPatched + extends OverrideAllThis, TComponent> { + variables?: ((this: TComponent) => TVariables) | TVariables; + subscribeToMore?: + | SubscribeToMoreOptionsPatched + | Array>; +} + export type VueApolloSmartQueryErrorHandler< TResult = any, TVariables = OperationVariables, TError = ApolloError, - TApp extends Vue = Vue + TComponent extends Vue = Vue > = ( error: TError, - vm: TApp, + vm: TComponent, key: string, type: 'query', - options: VueApolloSmartQueryOptions, + options: VueApolloSmartQueryOptions, ) => void; -// Type of VueApolloQueryDefinition['subscribeToMore'] is incompatible with generated QueryVariables types. -// Omitting it here since we don't use it anyway. export type VueApolloSmartQueryOptions< TResult = any, TVariables = OperationVariables, TError = ApolloError, - TApp extends Vue = Vue -> = Omit, 'subscribeToMore' | 'error'> & { - error?: VueApolloSmartQueryErrorHandler; + TComponent extends Vue = Vue +> = VueApolloQueryDefinitionPatched & { + error?: VueApolloSmartQueryErrorHandler; }; export function createSmartQueryOptionsFunction( query: DocumentNode, onError?: ApolloOperationErrorHandlerFunction, -): ( - options?: Partial>, -) => VueApolloQueryDefinition { +): ( + options?: Partial, 'query'>>, +) => VueApolloSmartQueryOptions { return (options = {}) => { const defaultErrorHandlerFn: VueApolloSmartQueryErrorHandler = ( error: TError, From 7a79a5c1fa72ed3ede0bd8033d5eed0b1afd8ccb Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 07:57:09 +1200 Subject: [PATCH 03/21] Add test for types and decorator --- package-lock.json | 23 ++++++ package.json | 4 +- test/example.ts | 181 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 test/example.ts diff --git a/package-lock.json b/package-lock.json index 526da95..a468cf5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4258,6 +4258,23 @@ "integrity": "sha512-dZjLPWNQqYv0dqV2RNbiFed0LtSp6yd4jchsDGnuhDKa9OQHJYCfovaOEvY91w9gqbYO7Se9LKDTl3xxYva/3w==", "dev": true }, + "graphql-tag": { + "version": "2.12.5", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.5.tgz", + "integrity": "sha512-5xNhP4063d16Pz3HBtKprutsPrmHZi5IdUGOWRxA2B6VF7BIRGOHZ5WQvDmJXZuPcBg7rYwaFxvQYjqkSdR3TQ==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "dev": true + } + } + }, "hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -10278,6 +10295,12 @@ } } }, + "vue-property-decorator": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-9.1.2.tgz", + "integrity": "sha512-xYA8MkZynPBGd/w5QFJ2d/NM0z/YeegMqYTphy7NJQXbZcuU6FC6AOdUAcy4SXP+YnkerC6AfH+ldg7PDk9ESQ==", + "dev": true + }, "vue-template-es2015-compiler": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", diff --git a/package.json b/package.json index 08a2f24..0d72746 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "eslint-plugin-promise": "4.3.1", "eslint-plugin-vue": "7.17.0", "graphql": "15.5.2", + "graphql-tag": "2.12.5", "husky": "7.0.2", "jest": "27.1.0", "jest-html-reporters": "2.1.6", @@ -72,7 +73,8 @@ "vue": "2.6.14", "vue-apollo": "3.0.7", "vue-class-component": "7.2.6", - "vue-jest": "3.0.7" + "vue-jest": "3.0.7", + "vue-property-decorator": "9.1.2" }, "engines": { "node": ">=12.9.0" diff --git a/test/example.ts b/test/example.ts new file mode 100644 index 0000000..3d8a1a0 --- /dev/null +++ b/test/example.ts @@ -0,0 +1,181 @@ +import { ApolloQueryResult } from 'apollo-client'; +import gql from 'graphql-tag'; +import { VueApolloQueryDefinition } from 'vue-apollo/types/options'; +import { Component, Vue } from 'vue-property-decorator'; +import { createSmartQueryOptionsFunction } from '../src'; +import { SmartQuery } from '../src/decorator'; + +// Create a query options function +const useTodoListQuery = createSmartQueryOptionsFunction(gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } +`); + +// Ensure that the result of the options function can be assigned to a regular VueApolloQueryDefinition +const options: VueApolloQueryDefinition = useTodoListQuery({ + variables: { + limit: 10, + skip: 0, + } +}); + +@Component +export class TodoList1 extends Vue { + @SmartQuery({ + query: gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `, + variables() { + return this.vars; + }, + }) + todos!: Todo[]; + + get vars(): QueryVariables { + return { + limit: 10, + skip: 0, + }; + } +} + +@Component({}) +export class TodoList2 extends Vue { + @SmartQuery(useTodoListQuery({ + skip() { + return this.foo === 'bar'; + }, + variables() { + return this.vars; + }, + })) + todos!: Todo[]; + + get vars(): QueryVariables { + return { + limit: 10, + skip: 0, + }; + } + + get foo(): string { + return 'bar'; + } +} + +@Component +export class TodoList3 extends TodoList1 { + @SmartQuery({ + query: gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `, + variables() { + return this.vars; + }, + }) + todos!: Todo[]; +} + +@Component +export class TodoList4 extends TodoList1 { + @SmartQuery({ + query: gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `, + variables() { + return this.vars; + }, + update(data: QueryResult) { + // data: QueryResult + }, + result({ data, errors, loading }) { + this.doThings(); + }, + subscribeToMore: { + document: gql``, + variables() { + return this.vars; + }, + }, + }) + todos!: Todo[]; + + doThings() { + // + } +} + +@Component +export class TodoList5 extends TodoList1 { + @SmartQuery({ + query: gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `, + variables() { + return this.vars; + }, + update(data: QueryResult) { + // data: QueryResult + }, + result(data: ApolloQueryResult) {}, + subscribeToMore: [ + { + document: gql``, + variables() { + return this.vars; + }, + updateQuery(prev, { subscriptionData: { data }, variables }) { + const vm: TodoList5 = this; + return { + ...prev, + todos: [ + { id: '1', title: 'Int' }, + { id: '2', title: 'Float' }, + { id: '3', title: 'String' }, + ], + }; + }, + }, + ], + }) + todos!: Todo[]; +} + +interface Todo { + id: string; + title: string; +} + +interface QueryResult { + todos: Todo[]; + __typename?: 'Query'; +} + +interface QueryVariables { + skip?: number; + limit?: number; +} From a184514f2c0a3b5a1300d8e5c15adc309cfb377a Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 07:59:26 +1200 Subject: [PATCH 04/21] Remove jest-html-reporters --- jest.config.js | 10 +------ package-lock.json | 75 ++--------------------------------------------- package.json | 1 - 3 files changed, 4 insertions(+), 82 deletions(-) diff --git a/jest.config.js b/jest.config.js index deeeccb..42addd7 100644 --- a/jest.config.js +++ b/jest.config.js @@ -12,13 +12,5 @@ module.exports = { }, collectCoverage: false, collectCoverageFrom: ['/components/**/*.vue', '/pages/**/*.vue'], - reporters: [ - 'default', - [ - 'jest-html-reporters', - { - filename: 'test/.results/test-results.html', - }, - ], - ], + reporters: ['default'], }; diff --git a/package-lock.json b/package-lock.json index a468cf5..53d18f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2054,12 +2054,6 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -3058,12 +3052,6 @@ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true - }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -4040,26 +4028,6 @@ "mime-types": "^2.1.12" } }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5771,16 +5739,6 @@ } } }, - "jest-html-reporters": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/jest-html-reporters/-/jest-html-reporters-2.1.6.tgz", - "integrity": "sha512-L81yXCctu0clmRl2rDeq5nWdH6Sy1U0IJgf+wy6wUTPcCmfg3JIfJnTug0mWSgQqtk0I5IMZ7Z+c4317uMNgMw==", - "dev": true, - "requires": { - "fs-extra": "^9.0.1", - "open": "^8.0.3" - } - }, "jest-jasmine2": { "version": "27.1.0", "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.1.0.tgz", @@ -6862,24 +6820,6 @@ "minimist": "^1.2.5" } }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, "keyv": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", @@ -8356,17 +8296,6 @@ "mimic-fn": "^2.1.0" } }, - "open": { - "version": "8.0.8", - "resolved": "https://registry.npmjs.org/open/-/open-8.0.8.tgz", - "integrity": "sha512-3XmKIU8+H/TVr8wB8C4vj0z748+yBydSvtpzZVS6vQ1dKNHB6AiPbhaoG+89zb80717GPk9y/7OvK0R6FXkNmQ==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -10176,7 +10105,9 @@ "vue-class-component": { "version": "7.2.6", "resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-7.2.6.tgz", - "integrity": "sha512-+eaQXVrAm/LldalI272PpDe3+i4mPis0ORiMYxF6Ae4hyuCh15W8Idet7wPUEs4N4YptgFHGys4UrgNQOMyO6w==" + "integrity": "sha512-+eaQXVrAm/LldalI272PpDe3+i4mPis0ORiMYxF6Ae4hyuCh15W8Idet7wPUEs4N4YptgFHGys4UrgNQOMyO6w==", + "dev": true, + "optional": true }, "vue-eslint-parser": { "version": "7.10.0", diff --git a/package.json b/package.json index 0d72746..8f6bed3 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,6 @@ "graphql-tag": "2.12.5", "husky": "7.0.2", "jest": "27.1.0", - "jest-html-reporters": "2.1.6", "lint-staged": "11.1.2", "mkdirp": "1.0.4", "np": "7.5.0", From 38efa7f5fdb8c377572c4261d855eb2a56313903 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 08:04:18 +1200 Subject: [PATCH 05/21] Run tsc build as part of test script --- package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8f6bed3..4f079b8 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,11 @@ "postbuild": "cp package.json README.md dist/", "lint": "eslint --ext .ts --ignore-path .gitignore .", "lint:fix": "eslint --ext .ts --ignore-path .gitignore . --fix", - "test": "jest", + "pretest": "rimraf dist", + "test": "tsc -p tsconfig.json && jest", "test:watch": "jest --watch", - "test:ci": "rimraf test/.results && mkdirp test/.results && jest --ci --runInBand --passWithNoTests", + "pretest:ci": "npm run pretest", + "test:ci": "tsc -p tsconfig.json && jest --ci --runInBand --passWithNoTests", "version": "npm run build", "postversion": "npm run postbuild", "release": "np --contents dist/", From 271af35ff3c8f04ec90edd42966b715688cdcb56 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 08:05:03 +1200 Subject: [PATCH 06/21] Remove vue-jest, use ts-jest only --- jest.config.js | 27 +-- package-lock.json | 453 ---------------------------------------------- package.json | 1 - 3 files changed, 14 insertions(+), 467 deletions(-) diff --git a/jest.config.js b/jest.config.js index 42addd7..d62a2e1 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,16 +1,17 @@ +const { pathsToModuleNameMapper } = require('ts-jest/utils'); +const { compilerOptions } = require('./tsconfig'); + module.exports = { - moduleNameMapper: { - '^@/(.*)$': '/$1', - '^~/(.*)$': '/$1', - '^vue$': 'vue/dist/vue.common.js', - }, - moduleFileExtensions: ['js', 'ts', 'vue', 'json'], - transform: { - '^.+\\.js$': 'babel-jest', - '^.+\\.ts?$': 'ts-jest', - '.*\\.(vue)$': 'vue-jest', - }, - collectCoverage: false, - collectCoverageFrom: ['/components/**/*.vue', '/pages/**/*.vue'], + preset: 'ts-jest', + testEnvironment: 'node', + roots: ['/src/', '/test/'], + testRegex: '\\.(spec|e2e-spec)\\.ts$', + testPathIgnorePatterns: ['/node_modules/'], + testTimeout: 20000, + moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { + prefix: '/', + }), + coveragePathIgnorePatterns: ['/node_modules/', '/test/'], + coverageDirectory: '/test/.coverage', reporters: ['default'], }; diff --git a/package-lock.json b/package-lock.json index 53d18f7..7013727 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1552,18 +1552,6 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, - "@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=", - "dev": true - }, - "@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true - }, "@types/yargs": { "version": "16.0.4", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", @@ -2054,71 +2042,6 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, "babel-jest": { "version": "27.1.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.1.0.tgz", @@ -2150,15 +2073,6 @@ } } }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, "babel-plugin-istanbul": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", @@ -2184,28 +2098,6 @@ "@types/babel__traverse": "^7.0.6" } }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, "babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", @@ -2236,95 +2128,6 @@ "babel-preset-current-node-syntax": "^1.0.0" } }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - }, - "dependencies": { - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - } - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2352,15 +2155,6 @@ } } }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, "boxen": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.0.1.tgz", @@ -2712,12 +2506,6 @@ "wrap-ansi": "^5.1.0" } }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -2856,12 +2644,6 @@ "safe-buffer": "~5.1.1" } }, - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "dev": true - }, "cosmiconfig": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", @@ -2906,18 +2688,6 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true }, - "css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - } - }, "cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", @@ -2958,16 +2728,6 @@ "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", "dev": true }, - "deasync": { - "version": "0.1.21", - "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.21.tgz", - "integrity": "sha512-kUmM8Y+PZpMpQ+B4AuOW9k2Pfx/mSupJtxOsLzmnHY2WqZUYRFccFn2RhzPAqt3Xb+sorK/badW2D4zNzqZz5w==", - "dev": true, - "requires": { - "bindings": "^1.5.0", - "node-addon-api": "^1.7.1" - } - }, "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -3007,12 +2767,6 @@ "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", "dev": true }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, "decompress-response": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-5.0.0.tgz", @@ -3876,15 +3630,6 @@ "tmp": "^0.0.33" } }, - "extract-from-css": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/extract-from-css/-/extract-from-css-0.4.4.tgz", - "integrity": "sha1-HqffLnx8brmSL6COitrqSG9vj5I=", - "dev": true, - "requires": { - "css": "^2.1.0" - } - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3959,12 +3704,6 @@ "flat-cache": "^3.0.4" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3974,24 +3713,6 @@ "to-regex-range": "^5.0.1" } }, - "find-babel-config": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", - "integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==", - "dev": true, - "requires": { - "json5": "^0.5.1", - "path-exists": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - } - } - }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -4735,15 +4456,6 @@ "side-channel": "^1.0.4" } }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -7473,15 +7185,6 @@ } } }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, "lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -7855,22 +7558,6 @@ } } }, - "node-addon-api": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", - "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", - "dev": true - }, - "node-cache": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-4.2.1.tgz", - "integrity": "sha512-BOb67bWg2dTyax5kdef5WfU3X8xu4wPg+zHzkvls0Q/QpYycIFRLEEIdAx9Wma43DxG6Qzn4illdZoYseKWa4A==", - "dev": true, - "requires": { - "clone": "2.x", - "lodash": "^4.17.15" - } - }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -9052,12 +8739,6 @@ "strip-indent": "^3.0.0" } }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, "regexpp": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", @@ -9133,12 +8814,6 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, "responselike": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", @@ -9346,19 +9021,6 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "source-map-support": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", @@ -9369,12 +9031,6 @@ "source-map": "^0.6.0" } }, - "source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "dev": true - }, "spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -9789,26 +9445,6 @@ } } }, - "tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", - "dev": true, - "requires": { - "@types/strip-bom": "^3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - } - } - }, "tsconfig-paths": { "version": "3.11.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", @@ -9968,12 +9604,6 @@ "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -10149,95 +9779,12 @@ } } }, - "vue-jest": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vue-jest/-/vue-jest-3.0.7.tgz", - "integrity": "sha512-PIOxFM+wsBMry26ZpfBvUQ/DGH2hvp5khDQ1n51g3bN0TwFwTy4J85XVfxTRMukqHji/GnAoGUnlZ5Ao73K62w==", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", - "chalk": "^2.1.0", - "deasync": "^0.1.15", - "extract-from-css": "^0.4.4", - "find-babel-config": "^1.1.0", - "js-beautify": "^1.6.14", - "node-cache": "^4.1.1", - "object-assign": "^4.1.1", - "source-map": "^0.5.6", - "tsconfig": "^7.0.0", - "vue-template-es2015-compiler": "^1.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "vue-property-decorator": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-9.1.2.tgz", "integrity": "sha512-xYA8MkZynPBGd/w5QFJ2d/NM0z/YeegMqYTphy7NJQXbZcuU6FC6AOdUAcy4SXP+YnkerC6AfH+ldg7PDk9ESQ==", "dev": true }, - "vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", - "dev": true - }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/package.json b/package.json index 4f079b8..10dcb2b 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,6 @@ "vue": "2.6.14", "vue-apollo": "3.0.7", "vue-class-component": "7.2.6", - "vue-jest": "3.0.7", "vue-property-decorator": "9.1.2" }, "engines": { From 1671a2a641001942d4853cd03926f73774deb7c3 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 08:11:04 +1200 Subject: [PATCH 07/21] Add VueApolloSmartQueryOptionsFunction type --- src/query.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/query.ts b/src/query.ts index 6a47b66..fcbafe5 100644 --- a/src/query.ts +++ b/src/query.ts @@ -64,12 +64,16 @@ export type VueApolloSmartQueryOptions< error?: VueApolloSmartQueryErrorHandler; }; +export type VueApolloSmartQueryOptionsFunction = < + TComponent extends Vue = TApp +>( + options?: Partial, 'query'>>, +) => VueApolloSmartQueryOptions; + export function createSmartQueryOptionsFunction( query: DocumentNode, onError?: ApolloOperationErrorHandlerFunction, -): ( - options?: Partial, 'query'>>, -) => VueApolloSmartQueryOptions { +): VueApolloSmartQueryOptionsFunction { return (options = {}) => { const defaultErrorHandlerFn: VueApolloSmartQueryErrorHandler = ( error: TError, From 2579221ef3dcc416e7821209a30b1abce230e7f9 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 11:47:17 +1200 Subject: [PATCH 08/21] Add SmartQuery decorator tests --- src/decorator/SmartQuery.spec.ts | 279 +++++++++++++++++++++++++++++++ tsconfig.json | 7 +- 2 files changed, 283 insertions(+), 3 deletions(-) create mode 100644 src/decorator/SmartQuery.spec.ts diff --git a/src/decorator/SmartQuery.spec.ts b/src/decorator/SmartQuery.spec.ts new file mode 100644 index 0000000..0d67f64 --- /dev/null +++ b/src/decorator/SmartQuery.spec.ts @@ -0,0 +1,279 @@ +import { ApolloQueryResult } from 'apollo-client'; +import gql from 'graphql-tag'; +import { Component, Vue } from 'vue-property-decorator'; +import { createSmartQueryOptionsFunction } from '../query'; +import { SmartQuery } from './SmartQuery'; + +interface Todo { + id: string; + title: string; +} + +interface QueryResult { + todos: Todo[]; + __typename?: 'Query'; +} + +interface QueryVariables { + skip?: number; + limit?: number; +} + +describe('@SmartQuery() decorator', () => { + it('Adds basic query options', () => { + @Component + class TodoList extends Vue { + @SmartQuery({ + query: gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `, + variables() { + return this.vars; + }, + }) + todos!: Todo[]; + + get vars(): QueryVariables { + return { + limit: 10, + skip: 0, + }; + } + } + + const instance = new TodoList(); + + expect(instance.$options.apollo?.todos).toEqual( + expect.objectContaining({ + query: expect.objectContaining({ definitions: expect.arrayContaining([]) }), + variables: expect.any(Function), + }), + ); + }); + + it('Works with a query options function', () => { + const useTodoListQuery = createSmartQueryOptionsFunction(gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `); + + @Component({}) + class TodoList extends Vue { + @SmartQuery( + useTodoListQuery({ + skip() { + return this.foo === 'bar'; + }, + variables() { + return this.vars; + }, + }), + ) + todos!: Todo[]; + + get vars(): QueryVariables { + return { + limit: 10, + skip: 0, + }; + } + + get foo(): string { + return 'bar'; + } + } + + const instance = new TodoList(); + + expect(instance.$options.apollo?.todos).toEqual( + expect.objectContaining({ + query: expect.objectContaining({ definitions: expect.arrayContaining([]) }), + skip: expect.any(Function), + variables: expect.any(Function), + }), + ); + }); + + it('Works with class inheritance and update, result methods', () => { + @Component + class TodoList extends Vue { + @SmartQuery({ + query: gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `, + variables() { + return this.vars; + }, + }) + todos!: Todo[]; + + get vars(): QueryVariables { + return { + limit: 10, + skip: 0, + }; + } + } + + @Component + class TodoList2 extends TodoList { + @SmartQuery({ + query: gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `, + variables() { + return this.vars; + }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + update(data: QueryResult) { + // data: QueryResult + }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + result({ data, errors, loading }) { + this.doThings(); + }, + subscribeToMore: { + document: gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `, + variables() { + return this.vars; + }, + }, + }) + todos!: Todo[]; + + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type + doThings() { + // + } + } + + const instance = new TodoList2(); + + expect(instance.$options.apollo?.todos).toEqual( + expect.objectContaining({ + query: expect.objectContaining({ definitions: expect.arrayContaining([]) }), + variables: expect.any(Function), + update: expect.any(Function), + result: expect.any(Function), + }), + ); + }); + + it('Supports subscribeToMore with updateQuery method', () => { + @Component + class TodoList extends Vue { + @SmartQuery({ + query: gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `, + variables() { + return this.vars; + }, + }) + todos!: Todo[]; + + get vars(): QueryVariables { + return { + limit: 10, + skip: 0, + }; + } + } + + @Component + class TodoList3 extends TodoList { + @SmartQuery({ + query: gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `, + variables() { + return this.vars; + }, + update(data: QueryResult) { + // data: QueryResult + }, + result(data: ApolloQueryResult) {}, + subscribeToMore: [ + { + document: gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } + `, + variables() { + return this.vars; + }, + updateQuery(prev, { subscriptionData: { data }, variables }) { + return { + ...prev, + todos: [ + { id: '1', title: 'Int' }, + { id: '2', title: 'Float' }, + { id: '3', title: 'String' }, + ], + }; + }, + }, + ], + }) + todos!: Todo[]; + } + + const instance = new TodoList3(); + + expect(instance.$options.apollo?.todos).toEqual( + expect.objectContaining({ + query: expect.objectContaining({ definitions: expect.arrayContaining([]) }), + variables: expect.any(Function), + update: expect.any(Function), + result: expect.any(Function), + subscribeToMore: expect.arrayContaining([ + expect.objectContaining({ + document: expect.objectContaining({ definitions: expect.arrayContaining([]) }), + variables: expect.any(Function), + updateQuery: expect.any(Function), + }), + ]), + }), + ); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index 646ed05..4c3becc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,9 +17,10 @@ "baseUrl": "./", "paths": { }, - "typeRoots": [ - "./node_modules/@types", - "./@types" + "types": [ + "@types/node", + "@types/jest", + "vue-apollo/types" ] }, "include":[ From 653651af9e7bef981b789606644cb7fa0ba2588c Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 11:47:38 +1200 Subject: [PATCH 09/21] Remove example test file --- test/example.ts | 181 ------------------------------------------------ 1 file changed, 181 deletions(-) delete mode 100644 test/example.ts diff --git a/test/example.ts b/test/example.ts deleted file mode 100644 index 3d8a1a0..0000000 --- a/test/example.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { ApolloQueryResult } from 'apollo-client'; -import gql from 'graphql-tag'; -import { VueApolloQueryDefinition } from 'vue-apollo/types/options'; -import { Component, Vue } from 'vue-property-decorator'; -import { createSmartQueryOptionsFunction } from '../src'; -import { SmartQuery } from '../src/decorator'; - -// Create a query options function -const useTodoListQuery = createSmartQueryOptionsFunction(gql` - query Todos($skip: Int, $limit: Int) { - todos(skip: $skip, limit: $limit) { - id - title - } - } -`); - -// Ensure that the result of the options function can be assigned to a regular VueApolloQueryDefinition -const options: VueApolloQueryDefinition = useTodoListQuery({ - variables: { - limit: 10, - skip: 0, - } -}); - -@Component -export class TodoList1 extends Vue { - @SmartQuery({ - query: gql` - query Todos($skip: Int, $limit: Int) { - todos(skip: $skip, limit: $limit) { - id - title - } - } - `, - variables() { - return this.vars; - }, - }) - todos!: Todo[]; - - get vars(): QueryVariables { - return { - limit: 10, - skip: 0, - }; - } -} - -@Component({}) -export class TodoList2 extends Vue { - @SmartQuery(useTodoListQuery({ - skip() { - return this.foo === 'bar'; - }, - variables() { - return this.vars; - }, - })) - todos!: Todo[]; - - get vars(): QueryVariables { - return { - limit: 10, - skip: 0, - }; - } - - get foo(): string { - return 'bar'; - } -} - -@Component -export class TodoList3 extends TodoList1 { - @SmartQuery({ - query: gql` - query Todos($skip: Int, $limit: Int) { - todos(skip: $skip, limit: $limit) { - id - title - } - } - `, - variables() { - return this.vars; - }, - }) - todos!: Todo[]; -} - -@Component -export class TodoList4 extends TodoList1 { - @SmartQuery({ - query: gql` - query Todos($skip: Int, $limit: Int) { - todos(skip: $skip, limit: $limit) { - id - title - } - } - `, - variables() { - return this.vars; - }, - update(data: QueryResult) { - // data: QueryResult - }, - result({ data, errors, loading }) { - this.doThings(); - }, - subscribeToMore: { - document: gql``, - variables() { - return this.vars; - }, - }, - }) - todos!: Todo[]; - - doThings() { - // - } -} - -@Component -export class TodoList5 extends TodoList1 { - @SmartQuery({ - query: gql` - query Todos($skip: Int, $limit: Int) { - todos(skip: $skip, limit: $limit) { - id - title - } - } - `, - variables() { - return this.vars; - }, - update(data: QueryResult) { - // data: QueryResult - }, - result(data: ApolloQueryResult) {}, - subscribeToMore: [ - { - document: gql``, - variables() { - return this.vars; - }, - updateQuery(prev, { subscriptionData: { data }, variables }) { - const vm: TodoList5 = this; - return { - ...prev, - todos: [ - { id: '1', title: 'Int' }, - { id: '2', title: 'Float' }, - { id: '3', title: 'String' }, - ], - }; - }, - }, - ], - }) - todos!: Todo[]; -} - -interface Todo { - id: string; - title: string; -} - -interface QueryResult { - todos: Todo[]; - __typename?: 'Query'; -} - -interface QueryVariables { - skip?: number; - limit?: number; -} From 2c102ffd8633b66be0221c2c61ffaeb9ae7cc00c Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 11:47:57 +1200 Subject: [PATCH 10/21] Revert "Run tsc build as part of test script" This reverts commit b5ebe6cdf56785aaa34db7476b79e10546b34204. --- package.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 10dcb2b..079ca4e 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,9 @@ "postbuild": "cp package.json README.md dist/", "lint": "eslint --ext .ts --ignore-path .gitignore .", "lint:fix": "eslint --ext .ts --ignore-path .gitignore . --fix", - "pretest": "rimraf dist", - "test": "tsc -p tsconfig.json && jest", + "test": "jest", "test:watch": "jest --watch", - "pretest:ci": "npm run pretest", - "test:ci": "tsc -p tsconfig.json && jest --ci --runInBand --passWithNoTests", + "test:ci": "rimraf test/.results && mkdirp test/.results && jest --ci --runInBand --passWithNoTests", "version": "npm run build", "postversion": "npm run postbuild", "release": "np --contents dist/", From 5316dffc79fafcc827405cfbb24357687832cb0d Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 11:51:55 +1200 Subject: [PATCH 11/21] Don't need to worry about test/.results directory any more --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 079ca4e..cd8c2be 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "lint:fix": "eslint --ext .ts --ignore-path .gitignore . --fix", "test": "jest", "test:watch": "jest --watch", - "test:ci": "rimraf test/.results && mkdirp test/.results && jest --ci --runInBand --passWithNoTests", + "test:ci": "jest --ci --runInBand --passWithNoTests", "version": "npm run build", "postversion": "npm run postbuild", "release": "np --contents dist/", From ffe674e17912138c70f14538c3f752081af8dfae Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 13:07:30 +1200 Subject: [PATCH 12/21] fix lint --- src/decorator/SmartQuery.spec.ts | 3 +++ src/decorator/SmartQuery.ts | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/decorator/SmartQuery.spec.ts b/src/decorator/SmartQuery.spec.ts index 0d67f64..c7d3325 100644 --- a/src/decorator/SmartQuery.spec.ts +++ b/src/decorator/SmartQuery.spec.ts @@ -225,9 +225,11 @@ describe('@SmartQuery() decorator', () => { variables() { return this.vars; }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars update(data: QueryResult) { // data: QueryResult }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function result(data: ApolloQueryResult) {}, subscribeToMore: [ { @@ -242,6 +244,7 @@ describe('@SmartQuery() decorator', () => { variables() { return this.vars; }, + // eslint-disable-next-line @typescript-eslint/no-unused-vars updateQuery(prev, { subscriptionData: { data }, variables }) { return { ...prev, diff --git a/src/decorator/SmartQuery.ts b/src/decorator/SmartQuery.ts index d5be829..b7cefb4 100644 --- a/src/decorator/SmartQuery.ts +++ b/src/decorator/SmartQuery.ts @@ -9,9 +9,7 @@ import { createDecorator, VueDecorator } from 'vue-class-component'; import { VueApolloSmartQueryOptions } from '../query'; export function SmartQuery( - options: TApp extends Vue - ? VueApolloSmartQueryOptions - : DocumentNode, + options: TApp extends Vue ? VueApolloSmartQueryOptions : DocumentNode, ): VueDecorator { return createDecorator((componentOptions: any, k: string) => { componentOptions.apollo = componentOptions.apollo || {}; From a55c4df8ac11d8a8626242e66926c4c0fa718416 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 13:10:07 +1200 Subject: [PATCH 13/21] Keep empty test directory --- test/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/.gitkeep diff --git a/test/.gitkeep b/test/.gitkeep new file mode 100644 index 0000000..e69de29 From 5f77e78dce7529afc28d2980d548893ff3bfad86 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 14:08:58 +1200 Subject: [PATCH 14/21] Add usage instructions to README.md --- README.md | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b1a7d2b..1ed3358 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,151 @@ # vue-apollo-smart-ops -Create TypeScript-typed operation functions for your Vue Apollo queries and mutations. +Creates TypeScript-typed operation functions for GraphQL queries and mutations compatible with +[Vue Apollo](https://apollo.vuejs.org/). + +This library is intended to be used together with the +[`typescript-vue-apollo-smart-ops` plugin](https://www.graphql-code-generator.com/docs/plugins/typescript-vue-apollo-smart-ops) +for [GraphQL Code Generator](https://www.graphql-code-generator.com/), but it may also be useful standalone. + +## Installation + +```shell +npm install --save vue-apollo-smart-ops +``` + +## Smart Query Usage + +### `createSmartQueryOptionsFunction(query: DocumentNode, onError?: ApolloOperationErrorHandlerFunction): VueApolloSmartQueryOptionsFunction` + +Returns a generated function which returns a [Vue Apollo Smart Query options object](https://apollo.vuejs.org/api/smart-query.html#options) +for the given query when called. + +> ⚠️ Note: The returned function is not meant to execute the query itself. It is only used to configure a Vue Apollo +> Smart Query. The responsibility for executing the query lies with Vue Apollo. + +The returned function accepts an options object as its first argument, allowing variables and other parameters to be +customised in runtime usage. Compared with creating an options object directly, the advantage here is that the options +accepted by the generated function are fully type-checked based on the query definition - and without needing to pass +type arguments at every usage. + +Using the [`@graphql-codegen/typescript-vue-apollo-smart-ops` plugin](https://www.graphql-code-generator.com/docs/plugins/typescript-vue-apollo-smart-ops) +you can automatically generate options functions for all of the query operations in your project. + +The following example manually creates an options function and assigns it to the variable `useTodoListQuery`: + +```typescript +const useTodoListQuery = createSmartQueryOptionsFunction(gql` + query Todos($skip: Int, $limit: Int) { + todos(skip: $skip, limit: $limit) { + id + title + } + } +`); +``` + +This function can subsequently be called inside the `apollo` options of a Vue component to configure a Smart Query. The +following example adds a `todos` Smart Query to a component, in Vue class component style: + +```typescript +@Component({ + apollo: { + todos: useTodoListQuery({ + skip() { + return this.foo === 'bar'; + }, + variables() { + return { + limit: 10, + skip: 0, + }; + }, + }) + } +}) +class TodoList extends Vue { + todos: Todo[] | null = null; + + get foo(): string { + return 'bar'; + } +} +``` + +### `@SmartQuery(options: VueApolloSmartQueryOptions)` + +The `@SmartQuery()` decorator works with your generated options functions to enable the declaration of Smart Queries +within the body of a Vue class component, instead of in the component options. This helps to keep the data property and +its query options together in one place. + +The following example is equivalent to the previous example but using the decorated syntax style: + +```typescript +@Component +class TodoList extends Vue { + @SmartQuery( + useTodoListQuery({ + skip() { + return this.foo === 'bar'; + }, + variables() { + return this.vars; + }, + }), + ) + todos: Todo[] | null = null; + + get foo(): string { + return 'bar'; + } +} +``` + +## Mutations Usage + +### `createMutationFunction(mutation: DocumentNode, onError?: ): MutationOperationFunction` + +Returns a generated function which executes a mutation and returns the result when called. + +The returned function requires a Vue app instance as its first argument (from which the `$apollo` client will be +accessed), and accepts an options object as its second argument, allowing variables and other parameters to be +customised in runtime usage. Compared with executing a mutation using the Vue Apollo client directly, the advantage here +is that the options accepted by the generated function are fully type-checked based on the operation definition - and +without needing to pass type arguments at every usage. + +Using the [`@graphql-codegen/typescript-vue-apollo-smart-ops` plugin](https://www.graphql-code-generator.com/docs/plugins/typescript-vue-apollo-smart-ops) +you can automatically generate mutation functions for all of the mutation operations in your project. + +The following example manually creates a mutation function and assigns it to the variable `todoCreateMutation`: + +```typescript +const todoCreateMutation = createMutationFunction(gql` + mutation TodoCreate($input: TodoInput!) { + todoCreate(input: $input) { + todo { + id + title + } + } + } +`); +``` + +The following example demonstrates how to call this mutation from a method on a component: + +```typescript +@Component +class TodoList extends Vue { + async onClickCreateTodoButton(): Promise { + const result = await todoCreateMutation(this, { + variables: { + title: 'Bake a cake', + }, + }); + + if (!result.success) { + throw new Error(`Failed to create Todo!`); + } + } +} +``` From 02a95b0068896af724281117d6ecfa91baf3c788 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 16:19:11 +1200 Subject: [PATCH 15/21] Simplify headings in README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1ed3358..1adfede 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ npm install --save vue-apollo-smart-ops ## Smart Query Usage -### `createSmartQueryOptionsFunction(query: DocumentNode, onError?: ApolloOperationErrorHandlerFunction): VueApolloSmartQueryOptionsFunction` +### `createSmartQueryOptionsFunction(query, onError?)` Returns a generated function which returns a [Vue Apollo Smart Query options object](https://apollo.vuejs.org/api/smart-query.html#options) for the given query when called. @@ -72,7 +72,7 @@ class TodoList extends Vue { } ``` -### `@SmartQuery(options: VueApolloSmartQueryOptions)` +### `@SmartQuery(options)` The `@SmartQuery()` decorator works with your generated options functions to enable the declaration of Smart Queries within the body of a Vue class component, instead of in the component options. This helps to keep the data property and @@ -103,7 +103,7 @@ class TodoList extends Vue { ## Mutations Usage -### `createMutationFunction(mutation: DocumentNode, onError?: ): MutationOperationFunction` +### `createMutationFunction(mutation, onError?)` Returns a generated function which executes a mutation and returns the result when called. From 47a9363624bc3b56db9c02669a364a3f82cc20e3 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 16:22:41 +1200 Subject: [PATCH 16/21] Remove --passWithNoTests We have a test now! --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cd8c2be..6e68f97 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "lint:fix": "eslint --ext .ts --ignore-path .gitignore . --fix", "test": "jest", "test:watch": "jest --watch", - "test:ci": "jest --ci --runInBand --passWithNoTests", + "test:ci": "jest --ci --runInBand", "version": "npm run build", "postversion": "npm run postbuild", "release": "np --contents dist/", From 0d681772973392d1f54b6611a3a5e5ccd1a2b84e Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Sun, 5 Sep 2021 16:25:13 +1200 Subject: [PATCH 17/21] 0.1.0-alpha.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7013727..6c095f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vue-apollo-smart-ops", - "version": "0.0.4", + "version": "0.1.0-alpha.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 6e68f97..48b2b63 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-apollo-smart-ops", - "version": "0.0.4", + "version": "0.1.0-alpha.1", "description": "Create TypeScript-typed operation functions for your Vue Apollo queries and mutations.", "author": "Madscience Ltd", "license": "MIT", From 1ca08f363ca4904a84134a04375971baad6d7832 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Mon, 6 Sep 2021 09:45:42 +1200 Subject: [PATCH 18/21] Type `loadingKey` query option as being a key of the component --- src/decorator/SmartQuery.spec.ts | 3 +++ src/query.ts | 17 ++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/decorator/SmartQuery.spec.ts b/src/decorator/SmartQuery.spec.ts index c7d3325..cb42e6f 100644 --- a/src/decorator/SmartQuery.spec.ts +++ b/src/decorator/SmartQuery.spec.ts @@ -76,10 +76,13 @@ describe('@SmartQuery() decorator', () => { variables() { return this.vars; }, + loadingKey: 'loading', }), ) todos!: Todo[]; + loading: number = 0; + get vars(): QueryVariables { return { limit: 10, diff --git a/src/query.ts b/src/query.ts index fcbafe5..10475e6 100644 --- a/src/query.ts +++ b/src/query.ts @@ -10,11 +10,6 @@ type OverrideAllThis = { [key in keyof O]: OverrideThis; }; -type VueApolloQueryDefinitionWithoutVariablesAndSubscribeToMore = Omit< - VueApolloQueryDefinition, - 'subscribeToMore' | 'variables' ->; - type SubscribeToMoreOptionsPatched = OverrideAllThis< Omit, 'updateQuery' | 'variables'>, TComponent @@ -34,12 +29,16 @@ type UpdateQueryFn TResult; -export interface VueApolloQueryDefinitionPatched - extends OverrideAllThis, TComponent> { +export interface VueApolloQueryDefinitionPatched + extends OverrideAllThis< + Omit, 'subscribeToMore' | 'variables' | 'loadingKey'>, + TComponent + > { variables?: ((this: TComponent) => TVariables) | TVariables; subscribeToMore?: | SubscribeToMoreOptionsPatched | Array>; + loadingKey?: keyof TComponent; } export type VueApolloSmartQueryErrorHandler< @@ -68,12 +67,12 @@ export type VueApolloSmartQueryOptionsFunction( options?: Partial, 'query'>>, -) => VueApolloSmartQueryOptions; +) => VueApolloSmartQueryOptions; export function createSmartQueryOptionsFunction( query: DocumentNode, onError?: ApolloOperationErrorHandlerFunction, -): VueApolloSmartQueryOptionsFunction { +): VueApolloSmartQueryOptionsFunction { return (options = {}) => { const defaultErrorHandlerFn: VueApolloSmartQueryErrorHandler = ( error: TError, From a318b10e972e2cf4613e84cc52e327d39aee9c4b Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Mon, 6 Sep 2021 09:46:05 +1200 Subject: [PATCH 19/21] 0.1.0-alpha.2 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6c095f8..d20b055 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vue-apollo-smart-ops", - "version": "0.1.0-alpha.1", + "version": "0.1.0-alpha.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 48b2b63..f5641a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-apollo-smart-ops", - "version": "0.1.0-alpha.1", + "version": "0.1.0-alpha.2", "description": "Create TypeScript-typed operation functions for your Vue Apollo queries and mutations.", "author": "Madscience Ltd", "license": "MIT", From e835aac336205e1b38986941caa72be950619d91 Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Mon, 6 Sep 2021 10:13:42 +1200 Subject: [PATCH 20/21] Improve grammar --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1adfede..245459b 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ accepted by the generated function are fully type-checked based on the query def type arguments at every usage. Using the [`@graphql-codegen/typescript-vue-apollo-smart-ops` plugin](https://www.graphql-code-generator.com/docs/plugins/typescript-vue-apollo-smart-ops) -you can automatically generate options functions for all of the query operations in your project. +you can automatically generate options functions for all the query operations in your project. The following example manually creates an options function and assigns it to the variable `useTodoListQuery`: @@ -114,7 +114,7 @@ is that the options accepted by the generated function are fully type-checked ba without needing to pass type arguments at every usage. Using the [`@graphql-codegen/typescript-vue-apollo-smart-ops` plugin](https://www.graphql-code-generator.com/docs/plugins/typescript-vue-apollo-smart-ops) -you can automatically generate mutation functions for all of the mutation operations in your project. +you can automatically generate mutation functions for all the mutation operations in your project. The following example manually creates a mutation function and assigns it to the variable `todoCreateMutation`: From c489613d123cdb370fdbdb615322988a09acf9be Mon Sep 17 00:00:00 2001 From: Simon Garner Date: Mon, 6 Sep 2021 10:15:51 +1200 Subject: [PATCH 21/21] Add credits to README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 245459b..15a0c3e 100644 --- a/README.md +++ b/README.md @@ -149,3 +149,8 @@ class TodoList extends Vue { } } ``` + +## Credits + +- `@SmartQuery()` decorator is based on the [vue-apollo-decorator](https://github.com/chanlito/vue-apollo-decorator) + package by chanlito, with some alteration to the types.